% SUBJECT: Professional GEM, 09.09.91
%
% These are all the sections. Appendix A-C are include files
% (app_a.tex, app_b.tex, app_c.tex).
%
% Layout changes:
%
% all sans-serif emphasizes removed 09.09.1991 - mo

% 4 Ollie's DIN-5 zoom...
% \documentstyle[12pt,a4,twoside,titlepage]{article}
%

\documentstyle[a4wide,twoside,titlepage]{article}

\pagestyle{headings}

%\textwidth15.6cm\textheight23cm

\sloppy

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\begin{document}

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

\title{Professional GEM}
\author{by Tim Oren}

\maketitle
\newpage

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\pagenumbering{roman}
\tableofcontents\clearpage
\newpage
\pagenumbering{arabic}

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\section{Introduction}

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Hello, world!}

   For those whom I have not met in person or  electronically, an
introduction is in order.

   I am a former member of the GEM programming team at Digital Research,
Inc., where I designed and implemented the GEM Resource Construction
Set and other parts of the GEM Programmer's Toolkit.  I have since
left DRI to become the user interface designer for Activenture, a
startup company which is developing CD-ROM technology for use with
the Atari ST and other systems.

   The purpose of Professional GEM is to pass along  some of the
information and tricks I have accumulated about GEM, and explore some
of the user interface techniques which a powerful graphics processor
such as the ST makes possible.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Ground Rules}

   I am going to assume that you have both a working  knowledge of the C
programming language and a copy of the ST Programmer's Toolkit with
documentation (available from Atari).  If you lack either, don't
panic.  You can read the columns to get the flavor of programming the
ST, and come back for a more serious visit later on.

   For now, I will be using code samples that will run with the
Atari-supplied C compiler, also known as DR C-68K, or Alcyon C.  I
will be using the portability macros supplied with the Toolkit, so
that the code will also be transferable to other GEM systems.

   Both of these items are subject to change, depending on  reader
feedback and the availability of better products.

   If you do not have a copy of the source to the {\tt DOODLE.C} GEM example
program, you should  consider downloading a copy from SIG*ATARI.
Although it is poorly documented, it shows real-life examples of many
of the techniques I will  discuss.

   Getting started with a windowed graphics system seems to be like
getting into an ice-cold swimming pool: it's best done all at once.

   Anyone who has looked at {\em Inside Macintosh} has probably noticed that
you have to have read most of it to understand any of it.  GEM isn't
really much  different.  You have all the reference guides in your
hand, but nothing to show how it all works together.

   I am hoping to help this situation by leading a series of short tours
through the GEM jungle.  Each time we'll go out with a particular
goal in mind and follow the path that leads there.  We'll look at the
pitfalls and strange bugs that lurk for the unwary, and show off a
few tricks to  amaze the natives.  The first trip leaves immediately;
our mission is to get a window onto the ST screen, with all of its
parts properly initialized.
\newpage

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\section{Windows}

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{We do windows}

   One of the most important services which a graphics interface system
provides for the user and programmer is window management.

   Windows allow the user to perform more than one activity on the same
screen, to freely reallocate areas of the screen for each task, and
even to pile the information up like pages of paper to make more
room.  The price for this increased freedom is (as usual) paid by
you, the programmer, who must master a more complex method of
interacting with the ``outside world''.

   The windowing routines provided by ST GEM are the most comprehensive
yet available in a low-cost microcomputer.  This article is a guide
to using these services in an effective manner.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{In the beginning}

   In GEM, creating a window and displaying it are two different
functions.  The creation function is called {\tt wind\_create}, and its
calling sequence is:

\begin{verbatim}
   handle = wind_create(parts, xfull, yfull, wfull, hfull);
\end{verbatim}

   This function asks GEM to reserve space in its memory for a new
window  description, and to return a code or {\em handle}\/ which you can
use to refer to the window in the future.  Valid window handles are
positive integers; they are not memory pointers.

   GEM can run out of window handles.  If it does so, the value returned
is negative.  Your code should always check for this  situation and
ask the program's user to close some windows and retry if  possible.
Handle zero is special.  It refers to the {\em desktop}, which is
predefined as light green (or gray) on the ST.  Window zero is always
present and may be used, but never deleted, by the programmer.

   The  {\tt xfull}, {\tt yfull}, {\tt wfull}, and {\tt hfull}\/ parameters
are integers which determine the maximum size of the window.
{\tt xfull}\/ and {\tt yfull}\/ define the upper left corner of the window,
and {\tt wfull}\/ and {\tt hfull}\/ specify its width and height.
(Note that all of the window coordinates which we use are in pixel units.)

   GEM saves these values so that the program can get them later when
processing  FULL requests.  Usually the best maximum size for a
window is the entire desktop area, excepting the menu bar.  You can
find this by asking {\tt wind\_get} for the working area of the desktop
(handle zero, remember):

\begin{verbatim}
   wind_get(0, WF_WXYWH, &xfull, &yfull, &wfull, &hfull);
\end{verbatim}

   Note that {\tt WF\_WXYWH}, and all of the other mnemonics used in this
article, are defined in the {\tt GEMDEFS.H} file in the ST Toolkit.

   The parts parameter of {\tt wind\_create} defines what features will be
included in the window when it is drawn.  It is a word of single bit
flags which indicate the presence/absence of each feature.  To
request multiple features, the flags are {\em or-ed}\/ together. The flags'
mnemonics and meanings are:

\begin{description}

\item[NAME] A one character high title bar at the top of the window.

\item[INFO] A second character line below the NAME.

\item[MOVER] This lets the user move the window around by {\em dragging}\/
         in the NAME area.  NAME also needs to be defined.

\item[CLOSER] A square box at the upper left.  Clicking this control
point asks that the window be removed from the screen.

\item[FULLER] A diamond at upper right.  Clicking this control point
requests that the window grow to its maximum size, or  shrink back
down if it is already big.

\item[SIZER] An arrow at bottom right.  Dragging the SIZER lets  the
user choose a new size for the window.

\item[VSLIDE] defines a right-hand scroll box and bar for the window.
By dragging the scroll bar, the user requests that the  window's
{\em viewport}\/ into the information be moved.   Clicking on the gray box
above the bar requests that  the window be moved up one {\em page}.
Clicking below the  bar requests a down page movement.  You have to
define  what constitutes a page or line in the context of your
application.

\item[UPARROW] An arrow above the right scroll bar.  Clicking here
requests that the window be moved up one {\em line\/}.  Sliders and arrows
almost always appear together.

\item[DNARROW] An arrow below the right scroll bar.  Requests that  window
be moved down a line.

\item[HSLIDE] These features are the horizontal equivalent of the
VSLIDE above.  They appear at the bottom of the window.  Arrows
LFARROW and RTARROW usually indicate {\em character\/} sized movement left
and right.
{\em Page}\/ sized movement has to be defined by each application.
RTARROW and LFARROW are the horizontal equivalents of the
vertical slider components.

\end{description}

   It is important to understand the correspondence between window
features and event messages which are sent to the application by the
GEM window manager.  If a feature is not included in a window's
creation,  the user cannot perform the corresponding action, and your
application will  never receive the matching message type.  For
example, a window without a {\tt MOVER}\/ may not be dragged by the user,
and your app will never get a {\tt WM\_MOVED}\/ message for that window.

   Another important principle is that the application itself is
responsible for implementing the user's window action request when a
message is received.  This gives the application a chance to accept,
modify, or reject the user's request.

   As an example, if a {\tt WM\_MOVED}\/  message is received, it indicates that
the user has dragged the window.  You might want to byte or word
align the requested position before proceeding to move the window.
The {\tt wind\_set} calls used to perform the actual movements will be
described in a minute$\ldots$

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Open, Sesame!}

  The {\tt wind\_open} call is used to actually make the window
appear on the screen.  It animates a {\em zoom box}\/ on the screen and
then draws in the window's frame.  The calling sequence is:

\begin{verbatim}
   wind_open(handle, x, y, w, h);
\end{verbatim}

   The handle is the one returned by {\tt wind\_create}. 
Parameters {\tt x}, {\tt y}, {\tt w},
and {\tt h}\/ define the initial location and size of the window.  Note that
these measurements INCLUDE all of the window frame parts which you
have requested. To find out the size of the area inside the frame,
you can use

\begin{verbatim}
 wind_get(handle, WF_WXYWH, &inner_x, &inner_y, &inner_w, &inner_h);
\end{verbatim}

   Whatever size you choose for the window display, it cannot be any
larger than the full size declared in {\tt wind\_create}.

   Here is a good place to take note of a useful utility for calculating
window sizes.  If you know the {\em parts list}\/ for a window, and its
inner or outer size, you can find the other size with the {\tt wind\_calc}
call:

\begin{verbatim}
   wind_calc(parts, kind, input_x, input_y, input_w, input_h,
             &output_x, &output_y, &output_w, &output_h);
\end{verbatim}

   Kind is set to zero if the input coordinates are the inner area, and
you are calculating the outer size.  Kind is one if the inputs are
the outer size and you want the equivalent inner size.  Parts are
just the same as in {\tt wind\_create}.

   There is one common bug in using {\tt wind\_open}.  If the {\tt NAME}\/
feature  is
specified, then the window title must be initialized BEFORE opening
the window:

\begin{verbatim}
   wind_set(handle, WF_NAME, ADDR(title), 0, 0);
\end{verbatim}

   If you don't do this, you may get gibberish in the NAME area or the
system may crash.   Likewise, if you have specified the INFO feature,
you must make a {\tt wind\_set} call for {\tt WF\_INFO}\/ before opening the
window.

Strings whose addresses are passed in the {\tt WF\_NAME}\/  and {\tt WF\_INFO}\/
{\tt wind\_set} calls must be allocated in a static data area.  Since the
AES remembers the addresses (not the characters), a disaster may result
if the storage has been reused when the window manager next attempts to
draw the window title area.

   Note  that {\tt ADDR()} specifies the 32-bit address of title.  This
expression is  portable to other (Intel-based) GEM systems.  If you
don't care about  portability, then \verb"&title[0]", or just \verb"title"
alone will work fine on the ST.


% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Cleaning Up}
  When you are done with a window, it should be closed
and deleted.  The call

\begin{verbatim}
   wind_close(handle);
\end{verbatim}

takes the window off the screen, redraws the desktop underneath it,
and animates a {\em zoom down}\/ box.  It doesn't delete the window's
definition, so you can reopen it later.

   Deleting the window removes its definition from the system, and makes
that handle available for reuse.  Always close windows before
deleting,  or you may leave a {\em dead}\/ picture on the screen.  Also be
sure to delete all  of your windows before ending the program, or
your app may {\em eat}\/ window  handles.  The syntax for deleting a window
is:

\begin{verbatim}
   wind_delete(handle);
\end{verbatim}


% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Those Fat Sliders}

  One of ST GEM's unique features is the
proportional slider bar.  Unlike other windowing systems, this type
of bar gives visual feedback on the fraction of a document which is
being viewed, as well as the position within the document.  The
catch, of course, is that you have two variables to maintain for each
scroll bar: size and position.

   Both bar size and position range from 1~to~1000.  A bar size of 1000
fills the slide box, and a value of one gets the minimum bar size.
To compute the proper size, you can use the formula:

\begin{verbatim}
   size = min(1000, 1000 * seen_doc / total_doc)
\end{verbatim}

   {\tt seen\_doc}\/ and {\tt total\_doc}\/ are the visible and total size of
the document
respectively, in whatever units are appropriate.  As an example, if
your window could show 20 lines of a 100 line text file, you should
set a slider size of 200.  Since the window might be bigger than the
total  document at some points, you need the maximum function.   If
the document size is zero, force the slider size to 1000.  (Note: You
will probably  need to do the computation above with 32-bit
arithmetic to avoid overflow  problems.)

   Once you have computed the size, use the {\tt wind\_set} function to
configure the scroll bar:

\begin{verbatim}
   wind_set(handle, WF_VSLSIZE, size, 0, 0, 0);
\end{verbatim}

   This call sets the vertical (right hand) scroll bar. 
Use {\tt WF\_HSLSIZE}\/
for the horizontal scroller.  All of these examples are done for the
vertical dimension, but the principles are identical in the other
direction.

   Bar positioning is a little tougher.   The most confusing aspect is
that the 1--1000 range does not set an absolute position of the bar
within the scroll box.  Instead, it positions the TOP of the bar
within its possible range of variation.

   Let's look at our text file example again to make this clearer.  If
there are always 20 lines of a 100 line file visible, then the top of
the window must be always be somewhere between line 1 and line 81.
This 80 line range is the actual freedom of movement of the window.
So, if the window were actually positioned with its top at line 61,
it would be at the three-quarter position within  the range, and we
should set a scroll bar position of 750.  The actual  formula for
computing the position is:

\begin{verbatim}
   pos = 1000 * (top_wind - top_doc) / (total_doc - seen_doc)
\end{verbatim}

   {\tt top\_wind}\/ and {\tt top\_doc}\/ are the top line in the current window and the
whole document, respectively.  Obviously, if {\tt seen\_doc} is greater or
equal to {\tt total\_doc}, you need to force a zero value for pos.  This
calculation may seem rather convoluted the first time through, but is
easy once you have done it.  When you have computed the position,
\verb"wind_set" configures the scroll bar:

\begin{verbatim}
   wind_set(handle, WF_VSLIDE, pos, 0, 0, 0);
\end{verbatim}

   {\tt WF\_HSLIDE}\/ is the equivalent for horizontal scrolling.

   It is a good practice to avoid setting the slider size or position if
they are already at the value which you need.  This avoids an
annoying redraw flash on the screen when it is not necessary.  You
can check on the current value of a slider parameter with {\tt wind\_get}:

\begin{verbatim}
   wind_get(handle, WF_VSLIDE, &curr_value, &foo, &foo, &foo);
\end{verbatim}

   {\tt foo}\/ is a dummy variable which needs to be there, but is not used.
Substitute {\tt WF\_VSLIDE}\/ with whatever parameter you are checking.

   One philosophical note on the use of sliders:  It is probably best to
avoid the use of both sliders at once unless it is clearly
appropriate to the type of data which is being viewed.

   Since Write and Paint programs make use of the sheet-of-paper
metaphor, moving the window around in both dimensions is reasonable.
However, if the data is more randomly organized, such as a tableau of
icons, then it is probably better to only scroll in  the vertical
dimension and {\em reshuffle}\/ if the window's width is changed. Then the
user only needs to manipulate one control to find information which
is off-screen.  Anyone who has had trouble finding a file or folder
within a Desktop window will recognize this problem.


% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Excelsior!}

  The file for this chapter is {\tt GEMCL02.C}.  All references  to non-GEM
routines in this column refer to this file.  Please note that  these
files will not contain entire programs.  Instead, they consist of
small pieces of utility code which you may use and modify in your
own  programs.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Redrawing windows}

  One of the most misunderstood parts of GEM is the correct method for
drawing within a window.  Most requests for redrawing are generated
by the GEM system, and arrive as messages (read with {\tt evnt\_multi})
which contain the handle of the window, and the screen rectangle
which is  {\em dirty}\/ and needs to be redrawn.

  Screen areas may become dirty as a result of windows being closed,
sized down, or moved, thus {\em exposing}\/ an area underneath.  The
completion of  a dialog, or closing of a desk accessory may also free
up a screen area which needs to be redrawn.  When GEM detects the
presence of a dirty rectangle,  it checks its list of open windows,
and sends the application a redraw message  for each of its windows
which intersects the dirty area.

  GEM does not {\em clip}\/ the rectangle which it sends to  the application;
that is, the rectangle may not lie entirely within the  portion of
the window which is exposed on the screen.  It is the job of the
application to determine in what portion of the rectangle it may
safely draw.   This is done by examining the {\em rectangle list}\/
associated with the window.

  A rectangle list is maintained by GEM for each active window.  It
contains the portions of the window's interior which are exposed,
i.e., topmost, on the screen and within which the app may draw.

  Let's consider an example to make this clear.  Suppose an app has
opened two windows, and there are no desk accessory windows open. The
window which is topmost will  always have only one rectangle in its
list.  If the two are separate on the  screen, then the second window
will also have one rectangle.  If they overlap,  then the top window
will "break" the rectangle of the bottom one.  If the  overlap is at
a corner, two rectangles will be generated for the bottom window.  If
the overlap is on a side only, then three rectangles are required to
cover  the exposed portion of the bottom window.  Finally, if the
first window is  entirely within the second, it requires four
rectangles in the list to tile the second window.

  Try working out a few rectangle examples with pencil and paper to
get the feel of it.  You will see that the possible combinations with
more  than two windows are enormous.  This, by the way, is the reason
that GEM does  not send one message for each rectangle on the list:
With multiple windows,  the number of messages generated would
quickly fill up the application's message queue.

  Finally, note that every app MUST use this method, even if it only
uses a single window, because there may be desk accessories with
their own  windows in the system at the same time.  If you do not use
the rectangle lists, you may overwrite an accessory's window.

  One more note on rectangles: although AES intersects the rectangles 
with the window work area, parts of a rectangle may be off screen because
the window is partially off screen. Redrawing may then lead to interesting
results. Intersecting a rectangle with the screen
{\tt GRECT} before redrawing will solve this problem.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Into the bits}

  First, we should note that the message type for a  redraw request is
{\tt WM\_REDRAW}, which is stored in \verb"msg[0]", the first location of the
message returned by {\tt evnt\_multi}.  The window handle is stored in
\verb"msg[3]".  These locations are the same for all of the message types
being discuss.  The rectangle which needs to be redrawn is stored in
\verb"msg[4]" through \verb"msg[7]".

  Now let's examine the sample redraw code in more detail. The redraw
loop is bracketed with mouse off and mouse on calls.  If you forget
to do  this, the mouse pointer will be over-written if it is within
the window and  the next movement of the mouse will leave a
rectangular blotch on the screen  as a piece of the {\em old}\/ screen is
incorrectly restored.

  The other necessary step is to set the window update flag.  This
prevents the menu manager from dropping a menu on top of the screen
portion being redrawn.  You must release this flag at the end of the
redraw, or the you will be unable to use any menus afterwards.

  The window rectangles are retrieved using a get-first, get-next
scheme which will be familiar if you have used the GEM DOS or PC-DOS
wildcard file calls.  The end of the rectangle list has been reached
when both the width and height returned are zero.  Since some part of
a  window might be off-screen (unless you have clamped its position -
see below), the retrieved rectangle is intersected with the desktop's
area,  and then with the screen area for which a redraw was
requested.

  Now you have the particular area of the screen in which it is  legal
to draw.  Unless there is only one window in your application, you
will have to test the handle in the redraw request to figure out what
to  put in the rectangle.

  Depending on the app, you may be drawing an AES  object tree, or
executing VDI calls, or some combination of the two.  In  the AES
case, the computed rectangle is used to specify the bounds of the
{\tt objc\_draw}.  For VDI work, the rectangle is used to set the clipping
area before executing the VDI calls.


% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{A small confession}

  At the beginning of this discussion, I  deliberately omitted one
class of redraws: those initiated by the application  itself.

  In some cases a part of the screen must be redrawn immediately to
give feedback to the user following a keystroke, button, or mouse
action.   In these cases, the application could call {\tt do\_redraw}
directly, without  waiting for a message.

  The only time you can bypass {\tt do\_redraw}, and draw  without walking the
rectangle list, is when you can be sure that the target  window is on
top, and that the figure being drawn is entirely contained  within it.

  In many cases, however, an application initiated redraw happens
because of a computed change, for instance, a spreadsheet update, and
its timing is not crucial.  In this instance, you may wish to have
the  app send ITSELF a redraw request.

  The main advantage of this approach  is that the AES is smart enough
to see if there is already a redraw request for the same window in
the queue, and, if so, to merge the requests by  doing a union of
their rectangles.  In this fashion, the {\em blinky}\/ appearance of
multiple redraws is avoided, without the need to include logic for
merging redraws within the program.

  A utility routine for sending the {\em self-redraw}\/ is included in
{\tt GEMCL02.C}.

     A number of developers reported that they were unable to get
the  self-redraw  technique to  work.
This is usually due to a bug in the {\tt appl\_init} binding in Alcyon C.
The  value  returned from the function,  which would  normally  be
assigned  to \verb"gl_apid",  is coming back as garbage.   To work around
the problem,  declare

\verb"EXTERN WORD gl_apid;"  

\noindent in your program and {\em do not}\/ assign the value from
{\tt appl\_init}. The binding WILL make  the assignment.


% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Window Control Requests}

  An application is notified by the AES, via the message system, when
the user manipulates one of the window control points.  Remember that
you must have specified each control point when the window was
created, or will not receive the associated control message.

  The most important thing to understand about window control is that
the change which the user requested does not take place until the
application forwards it to the AES.  While this makes for a little
extra work,  it gives the program a chance to intervene and validate
or modify the request to suit.

  A second thing to keep in mind is that not all window updates cause a
redraw request to be generated for the window, because the AES
attempts to save time with raster moves on the screen.

  Now let's look at each window control request in detail.  The
message code for a window move is {\tt WM\_MOVED}.  If you are willing to
accept  any such request, just do:

\begin{verbatim}
  wind_set(wh, WF_CXYWH, msg[4], msg[5], msg[6], msg[7]);
\end{verbatim}

  (Remember that {\tt wh}, the window handle, is always in \verb"msg[3]").
\vskip.2cm

  The AES will not request a redraw of the window following this call,
unless the window is being moved from a location which is partially
{\em off-screen}. Instead, it will do a {\em blit}\/ (raster copy) of the
window and its contents to the new location without intervention by
the app.

  There are two constraints which you may often wish to apply to  the
user's move request.  The first is to force the new location to lie
entirely within the desktop, rather than partially off-screen.  You
can do this with the {\tt rc\_constrain} utility by executing:

\begin{verbatim}
  rc_constrain(&full, &msg[4]);
\end{verbatim}

\noindent before making the {\tt wind\_set} call.  ({\tt full}\/ is assumed to contain
the desktop dimensions.) 

  The second common constraint is to {\em snap}\/ the x-dimension location of
the new location to a word boundary.  This operation will speed up
GEM's {\em blit}\/ because no shifting or masking will need to be done
when moving the window.  To perform this operation, use {\tt align()}
before the  {\tt wind\_set} call:

\begin{verbatim}
  msg[4] = align(msg[4], 16);
\end{verbatim}

  Calling {\tt wind\_set} with an x-coordinate of -1
will cause the left border of the window not to be displayed, which is 
especially convenient when snapping to word boundaries.

  The message code for a window size request is {\tt WM\_SIZED}.  Again, if
you are willing to accept any request, you can just {\em turn it around}\/
with the same {\tt wind\_set} call as given for {\tt WM\_MOVED}.

  Actually, GEM enforces a couple of constraints on sizing.  First, the
window may not be sized off screen.  Second, there is a minimum
window size which is dependent on the window components specified
when it was created.  This prevents features like scroll arrows from
being squeezed into oblivion.

  The most common application constraint on sizing is to snap the size
to horizontal words (as above) and/or vertical character lines.  In
the latter case, the vertical dimension of the output font is used
with {\tt align()}.

  Also,  be aware that the size message which you receive specifies the
EXTERNAL  dimensions of the window.  To assure an {\em even}\/ size for the
INTERNAL dimensions, you must make a {\tt wind\_calc} call to compute them,
use {\tt align()} on the computed values, back out the corresponding
external dimensions with the reverse {\tt wind\_calc}, and then make the
{\tt wind\_set} call with this set of values.

  A window resize will only cause a redraw request for the window if
the size is being increased in at least one dimension.  This is
satisfactory for most applications, but if you must {\em reshuffle}\/ the
window after a  size-down, you should send yourself a redraw (as
described above) after you make the {\tt wind\_set} call.  This will
guarantee that the display is updated correctly.  Also note that the
sizing or movement of one window may cause redraw requests to be
generated for other windows which are uncovered by the change.

  The window full request, with code {\tt WM\_FULLED}, is actually a toggle.
If the window is already at its full size (as specified in the
{\tt wind\_create}), then this is a request to shrink to its previous size.
If the window is currently small, then the request is to grow to full
size.

  Since the AES records the current, previous, and maximum window size,
you can use  {\tt wind\_get} calls to determine which situation pertains.
The {\tt hndl\_full} utility in {\tt GEMCL2.C} (modified from Doodle), shows
how to do this.

  The {\em zoom box}\/ effects when changing size are optional, and can be
removed  to speed things up.  Again, if the window's size is
decreasing, no redraw is  generated, so you must send yourself one if
necessary.  You should not have  to perform any constraint or {\em snap}\/
operations here, since (presumably) the  full and previous sizes have
had these checks applied to them already.

  The {\tt WM\_CLOSED} message is received when the close box is clicked. What
action you perform depends on the application.  If you want to remove
the window, use {\tt wind\_close} as described earlier.  In many
applications, however, the close message may indicate that a file is
to be saved, or a directory or editing level is to be closed.  In
these cases, the message is used to trigger this action before or
instead of the {\tt wind\_close}.  (Folders on the Desktop are an example of
this situation.)

  The {\tt WM\_TOPPED}\/ message indicates that the AES wants to bring the
indicated window to the {\em top}\/ and make it active.  This happens if
the user clicks within a window which is not on top, or if the
currently topped window is closed by its application or desk
accessory.  Normally, the application should respond to this message
with:

\begin{verbatim}
  wind_set(wh, WF_TOP, 0, 0);
\end{verbatim}

\noindent and allow the process to complete.

  In a few instances, a window may be used in an output only mode, such
as a status display, with at least one other window present for
input.  In this case, a {\tt WM\_TOPPED}\/ message for the status window may
be ignored.  In all other cases, you must handle the {\tt WM\_TOPPED}\/ 
message even if your application has only one window: Invocation of a
desk accessory could always place another window on top.  If you fail
to do so, subsequent redraws for your window may not be processed
correctly.


% bis hier wurden Funktionen in sans serif gesetzt
% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Window Slider Messages}

  If you specify all of the slider bar parts for your window, you may
receive up to five different message types for each of the two sets
of sliders.  To simplify things a little, I will discuss everything
in terms of the vertical (right hand side) sliders.  If you are also
using the horizontal sliders, the same techniques will work, just use
the alternate mnemonics.

  The \verb"WM_VSLID" message indicates that the user has dragged the slider
bar within its box, indicating a new relative position within the
document.  Along with the window handle, this message includes the
relative position between 1 and 1000 in \verb"msg[4]".

  Recall from the previous discussion that this interval corresponds
to the "freedom of movement" of the slider. If you want to accept the
user's request, just make the call:

\begin{verbatim}
  wind_set(wh, WF_VSLIDE, msg[4], 0, 0, 0);
\end{verbatim}

  (Corresponding horizontal mnemonics are \verb"WM_HSLID" and \verb"WF_HSLIDE").

  Note that this \verb"wind_set" call will not cause a redraw message to be
sent.  You must update the display to reflect the new scrolled
position, either by executing a redraw directly, or by sending
yourself a message.

  If the document within the window has some structure, you may not
wish to accept all slider positions.  Instead you may want to force
the scroll position to the nearest text line (for instance).  Using
terms defined in the last column, you may convert the slider position
to "document units" with:

\begin{verbatim}
  top_wind = msg[4] * (total_doc - seen_doc) / 1000 + top_doc
\end{verbatim}

  (This will probably require 32-bit arithmetic).

  After rounding off or otherwise modifying the request, convert it
back to slider units and make the \verb"WF_VSLIDE" request.

  The other four slider requests all share one message code:
\verb"WM_ARROWED".  They are distinguished by sub-codes stored in \verb"msg[4]":
\verb"WA_UPPAGE", \verb"WA_DNPAGE", \verb"WA_UPLINE", and \verb"WA_DNLINE".  These are produced
by clicking above and below the slider, and on the up and down
arrows, respectively.  (I have no idea why sub-codes were used in
this one instance.)  The corresponding horizontal slider codes are:
\verb"WA_LFPAGE", \verb"WA_RTPAGE", \verb"WA_LFLINE", and \verb"WA_RTLINE".

  What interpretation you give to these requests will depend on  the
application.  In the most common instance, text documents, the
customary method is to change the top of window position (top\_wind)
by  one line for a \verb"WA_UPLINE" or \verb"WA_DNLINE", and by {\tt seen\_doc} (the
number of lines in the window) for a \verb"WA_UPPAGE" or \verb"WA_DNPAGE".

  After making the change, compute a new slider position, and make the
\verb"wind_set" call as given above.  If the document's length is not an
even multiple of "lines" or "pages" you will have to be careful that
incrementing or  decrementing {\tt top\_wind} does not exceed its range of
freedom:
{\tt top\_doc} to ({\tt top\_doc} + {\tt total\_doc} - {\tt seen\_doc}).

  If you have such an odd size document, you will also have to make a
decision on whether to violate the line positioning rule so that the
slider may be put at its bottom-most position, or to follow the rule
but make it impossible to get the slider to the extreme of its range.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{A common bug}

  It is easy to forget that user clicks are not the only things that
affect slider position.  If the window size changes as a result of a
\verb"WM_SIZED" or \verb"WM_FULLED" message, the app must also  update its sliders
(if they are present).  This is a good reason to keep the top of
window information in "document units".

  You can just redo the position calculation with the new {\tt seen\_doc}\/
value, and call \verb"wind_set".  Also remember that changing the size of
the underlying document  (adding or deleting a bottom line, for
instance) must also cause the sliders  to be adjusted.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Dept.~of Dirty Tricks}

  There are two remaining window calls which are useful to advanced
programmers.  They require techniques which I have not yet discussed,
so you may need to file them for future reference.

  The AES maintains a quarter-screen sized buffer which is used to save
the area under alerts and menu drop-downs.  It is occasionally useful
for the application to gain access to this buffer for its own use in
saving screen areas with raster copies.  To do so, use:

\begin{verbatim}
  wind_get(0, WF_SCREEN, &loaddr, &hiaddr, &lolen, &hilen);
\end{verbatim}

  {\tt hiaddr} and {\tt loaddr} are the top and bottom 16-bits (respectively) of
the  32-bit address of the buffer.  {\tt hilen} and {\tt lolen} are the two
halves of  its length.

  Due to a preculiarity of the binding you have to reassemble  these
pieces before using them.  (The actual value of \verb"WF_SCREEN" is 17; this
does not appear in some versions of the {\tt GEMDEFS.H} file.)

  If you use this buffer, you MUST prevent menus from dropping down by
using either the \verb"BEG_UPDATE" or \verb"BEG_MCTRL" \verb"wind_update" calls.  Failure
to do so will result in your data being destroyed.  Remember to use
the matching \verb"wind_update": \verb"END_UPDATE" or \verb"END_MCTRL",
when you are done.

  The other useful call enables you to replace the system's desktop
definition with a resource of your choosing.  The call:

\begin{verbatim}
  wind_set(0, WF_NEWDESK, tree, 0, 0);
\end{verbatim}

where {\tt tree}\/ is the 32-bit address of the object tree, will cause the
AES to draw your definition instead of the usual gray or green
background. Not only that, it will continue to redraw this tree with
no intervention on your part.

  Obviously, the new definition must be carefully built to fit the
desktop area exactly or garbage will be left around the edges.  For
the truly sophisticated, a user-defined object could be used in this
tree, with the result that your application's code would be entered
from the AES whenever the desktop was redrawn.  This would allow you
to put VDI pictures or complex images onto the desktop background.

  This concludes our tour of GEM's basic window management techniques.
There have been some unavoidable glimpses of paths not yet taken
(forward references), but we will discuss those soon.

  In the next chapter, we will take a look at techniques for handling
simple dialog boxes, and start exploring the mysteries of resources
and object trees.


\newpage

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\section{The Dialog Handler}

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{A meaningful dialog}

   We will now start an exploration of ST GEM's dialog
handler.  I will discuss basic system calls for presenting the
dialog, and then continue with techniques for initializing and
reading on/off button and "radio" button objects.  We  will also take
some short side-trips into the operation of the GEM Resource
Construction Set to assist you in building these dialogs.

   There are a number of short C routines which accompany this chapter.
These are found in {\tt GEMCL03.C}.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Defining terms}

   A dialog box is an "interactive form" in which the user may enter
text and indicate selections by pointing with the mouse. Dialogs in
GEM are "modal", that is, when a dialog is activated other screen
functions such as menus and  window controls are suspended until the
dialog is completed.

   In most cases, the visual structure of a GEM dialog is specified
within your application's resource file.  The GEM Resource
Construction Set (RCS) is used to build a picture of the dialog.

   When the RCS writes out a resource, it converts that picture into a
tree of GEM drawing objects and stores this data structure within the
resource.  Before your application can  display the dialog, it must
load this resource file and find the  address of the tree which
defines the dialog.

   To load a resource, the AES checks its size and allocates memory for
the load.  It then reads in the resource, adjusting internal pointers
to reflect the load address.  Finally, the object sizes stored in the
resource are converted from characters to pixels using the system
font size.

   (A note for those with Macintosh experience:  Although Mac and GEM
resources share a name, there are fundamental differences which can
be misleading.  A Mac resource is a fork within a file; a GEM
resource is a TOS file by itself.  Mac resources may be paged in and
out of memory; GEM resources are monolithic.  GEM resources are
internally tree structured; Mac resources are not.  Finally, Mac
resources include font information, while ST GEM does this with font
loading at the VDI level.)

   The resource load is done with the GEM AES call:

\begin{verbatim}
   ok = rsrc_load(ADDR("MYAPP.RSC"));
\end{verbatim}

   {\tt MYAPP}\/ should be replaced with the name of your program. Resources
conventionally have the same primary name as their application, with
the RSC extent name instead of PRG.  The {\tt ok}\/ flag returned by
\verb"rsrc_load" will be FALSE is anything went wrong during the load.

   The most common causes of failure are the resource not being in the
application's subdirectory, or lack of sufficient memory for GEM to
allocate space for the resource.  If this happens, you must terminate
the program immediately.

   Once you have loaded the resource, you find the address of a dialog's
object tree with:

\begin{verbatim}
   rsrc_gaddr(R_TREE, MYDIALOG, &tree);
\end{verbatim}

{\tt tree} is a 32-bit variable which will receive the address of the root
node of the tree.

   The mnemonic \verb"MYDIALOG" should be replaced with the name you gave your
dialog when defining it in the RCS.  At the same time that it writes
the resource, RCS generates a corresponding {\tt .H} file containing tree
and object names.  In order to use these mnemonics within your
program, you must include the name file in your compile:  

\begin{verbatim}
#include "MYAPP.H"
\end{verbatim}

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Bug Alert!}

   When using the DRI/Alcyon C compiler, {\tt .H} files must be in the
compiler's home directory or they will not be found.  This is
especially annoying using a two floppy drive ST development system.
The only way around this is to explicitly  reference an alternate
disk in the \verb"#include", for instance:  \verb"B:MYAPP.H"

   Now that the address of the dialog tree has been found, you are ready
to display it.  The standard (and minimal) sequence for doing so is
given in routine \verb"hndl_dial()" in {\tt GEMCL03.C}.  We will now walk
through each step in this procedure.

   The \verb"form_center" call establishes the location of the dialog on the
screen.  Dialog trees generated by the RCS have an undefined origin
(upper-left corner).

   \verb"Form_center" computes the upper-left location necessary to center the
dialog on the screen, and inserts it into the \verb"OB_X" and \verb"OB_Y" fields of
the \verb"ROOT" object of the tree.  It also computes the screen rectangle
which the dialog will occupy on screen and writes its pixel
coordinates into variables {\tt xdial}, {\tt ydial}, {\tt wdial}, and {\tt hdial}.

   There is one peculiarity of \verb"form_center" which occasionally causes
trouble.  Normally the rectangle returned in {\tt xdial}, etc., is exactly
the same size as the basic dialog box.

   However, when the \verb"OUTLINED" enhancement has been specified for the
box, \verb"form_center" adds a three pixel margin to the rectangle returned.
This causes the screen area under the outline to be correctly redrawn
later (see below).  Note that \verb"OUTLINED" is part of the standard dialog
box in the RCS.  Other enhancements, such as \verb"SHADOWED" or "outside"
borders are NOT handled in this fashion, and you must compensate  for
them in your code.

   The next part of the sequence is a \verb"form_dial" call with a zero
parameter.  This reserves the screen for the dialog action about to
occur. Note that the C binding given for \verb"form_dial" in the DRI
documents is in error: there are nine parameters, not five.  The
first set of xywh arguments is actually used with \verb"form_dial" calls 1
and 2 only, but place holders must be supplied in all cases.

   The succeeding \verb"form_dial" call (parameter one) animates a "zoom box"
on the screen which moves and grows from the first screen rectangle
given to the second rectangle, where the dialog will be displayed.

   The use of this call is entirely optional.  In choosing whether to
use it or not, you should consider whether the origin of the "zoom"
is relevant to the  operation.  For instance, a zoom from the menu
bar is relatively meaningless, while a zoom from an object about to
be edited in the dialog provides visual feedback to the user, showing
whether the correct object was chosen.

   If the origin is not relevant, then the zoom is just a time-waster.
If  you decide to include these effects, consider a "preferences"
option in  your app which will allow the experienced and jaded user
to turn them off in the interests of speed.

   The \verb"objc_draw" call actually displays the dialog on the screen. Note
that the address of the tree, the beginning drawing object, and the
drawing depth are passed as arguments, as well as the rectangle
allotted for the dialog.

   In general, dialogs (and parts of dialogs) are  ALWAYS drawn
beginning at the ROOT (object zero).  When you want to draw  only a
portion of the dialog, adjust the clipping rectangle, but not the
object number.  This ensures that the background of the dialog is
always  drawn correctly.

   The \verb"objc_xywh()" utility in the listing can be used to find the
clipping rectangle for any object within a dialog, though you may
have to allow an extra margin is you have used shadows, outlines, or
outside borders with the object.

   Calling \verb"form_do" transfers control to the AES, which animates the
dialog for user interaction.  The address of the dialog tree is
passed as a parameter.  The second paramter is the number of the
editable object at which the text cursor will first be positioned.
If you have no text fields, pass a zero.  Note that again the DRI
documents are in error: passing a -1 default may crash the system.
Also be careful that the default which you specify is actually a text
field; no error checking is performed.

   The \verb"form_do" call returns the number of the object on which the user
clicked to terminate the dialog.  Usually this is a button type
object with the \verb"EXIT" and \verb"SELECTABLE" attributes set.  Setting the
\verb"DEFAULT" attribute as well will cause an exit on that object is a
carriage return is struck while in the dialog.

   If the top bit of the return is set, it indicates that  the exit
object had the \verb"TOUCHEXIT" attribute and was selected with a
double-click.  Since very few dialogs use this combination, the
sample code simply masks off the top bit.

   The next \verb"form_dial" call reverses the "zoom box", moving it from the
dialog's location back to the given x,y,w,h.  The same cautions apply
here as above.

   The final \verb"form_dial" call tells GEM that the dialog is complete, and
that the screen area occupied by the dialog is now considered "dirty"
and needs to be redrawn.  Using the methods described in the previous
chapter, GEM then sends redraws to all windows which were overlaid,
and does any necessary redrawing of the menu or desktop itself.

   There is one notable "feature" of \verb"form_dial(3)":  It always redraws
an area which is two pixels wider and higher than your request!  This
was probably included to make sure that drop-shadows were cleaned up,
and is usually innocuous.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{A handy trick}

   Use of the \verb"form_dial(3)" call is not limited to dialogs.  You can
use it to force the system to redraw any part of the screen.  The
advantage of this method is that the redraw area need not lie
entirely within a window, as was necessary with the {\tt send\_redraw}\/
method detailed in the last chapter.  A disadvantage is that this
method is  somewhat slower, since the AES has to decide who gets the
redraws.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Clean up}

   As a last step, you need to clear the \verb"SELECTED" flag in the object
which was clicked.  If you do not do this, the object will  be drawn
inverted the next time you call the dialog.  You could clear the flag
with the GEM \verb"objc_change" call, but it is inefficient since you do
not need to redraw the object.

   Instead, use the \verb"desel_obj()" code in the  listings, which modifies
the object's \verb"OB_STATE" field directly.  Assuming  that {\tt ret\_obj}
contains the exit object returned by \verb"hndl_dial", the call:

\begin{verbatim}
   desel_obj(tree, ret_obj);
\end{verbatim}

will do the trick.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Recap}

   The basic dialog handling method I have described contains three
steps: initialization ({\tt rsrc\_gaddr}\/), dialog presentation ({\tt hndl\_dial}\/),
and cleanup ({\tt desel\_obj}\/).

   As we build more advanced dialogs, these same basic steps will be
performed, but they will grow more complex. The initialization will
include setting up proper object text and states, and the cleanup
phase will also interrogate the final states of objects to find out
what the user did.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Button, button}

   The simple dialogs described above contain only exit buttons as
active objects.  As such, they are little more than glorified alert
boxes.

   We will now increase the complexity a little by considering non-exit
buttons.  These are constructed by setting the \verb"SELECTABLE" attribute
on a button object.  At run-time, such an object will toggle its
state between selected (highlighted) and non-selected  whenever the
user clicks on it.  (You can set the \verb"SELECTABLE" attribute  of other
types of objects and use them instead of actual buttons, but  be sure
that the user will be able to figure out what you intend!)

   Having non-exit buttons forces us to consider the problem of
initializing them before the dialog, and interrogating and resetting
them afterward.

   Since a button is a toggle, it is usually associated with a flag
variable in the program.  As part of the initialization, you should
test the flag variable, and if true call:

\begin{verbatim}
   sel_obj(tree, BTNOBJ);
\end{verbatim}

which will cause the button to appear highlighted when the dialog is
first drawn.  \verb"Sel_obj()" is in the listing.  \verb"BTNOBJ" is replaced with
the  name you gave your button when you defined it in the RCS.  Since
the button starts out deselected, you don't have to do anything if
your flag variable is false.

   After the dialog has completed, you need to check the object's state.
The \verb"selectp()" utility does so by masking the \verb"OB_STATE" field.  You can
simply assign the result of this test to your flag variable, but be
sure that the dialog was exited with an OK button, not with a CANCEL!
Again, remember to clean up the button with \verb"desel_obj()". (It's often
easiest to deselect all buttons just before you leave the dialog
routine, regardless of the final dialog state.)

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Who's got the button?}

   Another common use of buttons in a  dialog is to select one of a set
of possible options.  In GEM, such objects are called radio buttons.
This term recalls automobile radio tuners where pushing in one button
pops out any others.  In like fashion, selecting any one of a set of
radio buttons automatically deselects all of the others.

   To use the radio button feature, you must do some careful work with
the Resource Construction Set.

   First, each member of a set of  radio buttons must be children of the
same parent object within the  object tree. To create this structure,
put a hollow box type object in the  dialog, make it big enough to
hold all of the buttons, and then put the buttons into the box one at
a time.

   By nesting the buttons within the  box object, you force them to be
its children.  Each of the buttons must have both the \verb"SELECTABLE" and
\verb"RADIO BUTTON" attributes set.  When you are done, you may make the
containing box invisible by setting its border to zero, {\em but do not
FLATTEN it!}

   Since each radio button represents a different option, you must
usually assign a name to each object.  When initializing the dialog,
you must check which option is currently set, and turn on the
corresponding button only.  A chain of if-then-else structures
assures that only one button will be selected.

   At the conclusion of the dialog, you must check each button with
\verb"selectp()" and make the appropriate adjustments to internal variables.
Again, an if-then-else chain is appropriate since only one button may
be selected.  Either deselect the chosen button within this chain or
do them all at the end.

   There is one common use of radio buttons in which you may short-cut
this procedure.  If the buttons each represent one possible value of
a numeric variable, for instance, a set of selector buttons
representing  colors from zero to seven, then you can compute the
initial object directly.

   In order for this technique to work, you must use a special
capability of the RCS.  Insert the object corresponding to a zero
value at the top (or left) of your array of buttons, then put the
"one" button below (or right) of it, and so on.

   When the buttons are complete,  the SORT operation is used to
guarantee that the top/left object is in fact the first child of the
parent box with the others following in order.  Due to the details of
object tree structure (to be discussed in the next column), this will
guarantee that these objects are contiguous in the resource.

   If you assign a name (say BUTTON1) to the first button,  then you can
initialize the correct button with the call:

\begin{verbatim}
   sel_obj(tree, BUTTON1 + field);
\end{verbatim}

where field is the variable of interest.

   When the dialog is complete, you can scan the radio buttons to
compute the new value for the underlying variable.  The \verb"encode()"
procedure in the listing will do this.  As always, remember to
deselect the buttons at the end.

   You can use offsets or multipliers if your variable's values don't
start with zero or increment by one.  If the values are irregular you
may be able to use a lookup table, at the cost of additional code.

   Next, I will discuss the internal structure of object
trees.  Then we'll use that knowledge to build a piece of code which
will "walk" an entire tree and apply a function to each object.
We'll apply this code to do all of the button deselects  with a
single call!  I'll also look at handling editable text fields and
discuss some ways to alter a dialog's appearance at run-time.

\newpage

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\section{Object Trees}

We are about to delve into the mysteries of GEM resource structure,
and then use this knowledge to create some useful utilities for
handling dialogs.  As before, there is once again a demonstration file.
You will find it under the name {\tt GEMCL04.C}.

   The first and largest part of the listing contains a C image of a
sample resource file.  To create this listing, I used the GEM
Resource  Construction Set to create a dummy resource with three
dialogs including examples of all object types, then enabled the C
output option and saved  the resource.  If you have access to a copy
of RCS, I suggest that you  create your own listing in order to get a
feel for the results.  Then, using  either listing as a roadmap to
the resource, you can follow along as  we enter...

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{A maze of twisty little passages}

While a GEM resource is loaded as a block of binary information, it
is actually composed of a number of different data structures.  These
structures are linked together in a rather tangled hierarchy.  Our
first job is to map this linkage system.

   The topmost structure in a resource file is the resource header.
This is an array of words containing the size and offset within the
resource of the other structures which follow.  This information is
used by  GEM during the resource load process, and you should never
need to access it. (The resource header does not appear in the C
output file; it is generated by the RSCREATE utility if the C file is
used to recreate the resource.)

   The next structure of interest is the tree index.  This is an
array of long pointers, each of which addresses the beginning of an
object tree. Again, you wouldn't normally access this structure
directly.  The GEM  \verb"rsrc_gaddr" call uses it when finding trees'
addresses.  This structure is called "rs\_trindex" in the C output.

   If you look at the contents of {\tt rs\_trindex}\/you will notice that the
values are integers, instead of the pointers I described.  What has
happened is that RCS has converted the pointers to indices into the
object array. (If you actually used the C file to recreate the
resource file, then the  pointers would be regenerated by RSCREATE.)

   Now you can follow the link from {\tt rs\_trindex}\/ to the objects stored
in {\tt rs\_object}.  Take (for instance) the second entry in {\tt rs\_trindex}\/ and
count down that many lines in {\tt rs\_object}.  The following line (object)
should start with a -1.  This indicates that it is the root object of
a tree.  The following objects down to the next root belong to that
tree. We'll pass over the details of inter-object linkage for now,
leaving it for later.

   There are a number of different fields in an object, but right now
we'll concentrate on two of them: \verb"OB_TYPE" and \verb"OB_SPEC".  The \verb"OB_TYPE"
is the field which contains mnemonics like \verb"G_STRING" and \verb"G_BOX"
indicating the type of the object.  The \verb"OB_SPEC" is the only field in
each object which  is a LONG - you can tell it by the L after the
number.

   What's in \verb"OB_SPEC" depends on the object type, so we need to talk
about what kinds of objects are available, what you might use them
for, and finally how they use the \verb"OB_SPEC" field.

   The box type objects are \verb"G_BOX", \verb"G_IBOX", and \verb"G_BOXCHAR".  A \verb"G_BOX" is
an opaque rectangle, with an optional border.  It's used to create a
solid patch of color or pattern on which to place other objects.  For
instance, the background of a dialog is a \verb"G_BOX".

   A \verb"G_IBOX" is a hollow box which has only a border.  (If the border
has no thickness, then the box is "invisible", hence the name.)  The
favorite use for IBOXes is to hold radio buttons.  There is also one
neat trick you can play with an IBOX.  If you have more than one
object (say an image and a string) which you would like to have
selected all at once, you can insert them in a dialog, then cover
them with an IBOX. Since the box is transparent, they will show
through.  If you now make the box selectable, clicking on it will
highlight the whole area at once!

   The \verb"G_BOXCHAR" is just like a \verb"G_BOX", except that a single character
is drawn in its center.  They are mostly used as "control points":
the \verb"FULLER", \verb"CLOSER", \verb"SIZER", and arrows in GEM windows are BOXCHARs, as
are  the components of the color selection gadgets in the RCS.

   The \verb"OB_SPEC" for box type objects is a packed bit array.  Its
various fields contain the background color and pattern, the border
thickness and color, and the optional character and its color.

   The string type objects are \verb"G_STRING", \verb"G_BUTTON", and \verb"G_TITLE".
\verb"G_STRINGs" (in addition to being a bad pun) are for setting up static
explanatory text within dialogs.  The characters are always written
in the "system font": full size, black, with no special effects.

   We have already discussed many of the uses of \verb"G_BUTTONs".  They add
a border around the text.  The thickness of a \verb"G_BUTTON"'s border is
determined by what flags are set for the object.  All buttons start
out with a border thickness of one pixel.  One pixel is added if the
\verb"EXIT" attribute is set, and one more is added if the \verb"DEFAULT" attribute
is set.

   The \verb"G_TITLE" type is a specially formatted text string used only in
the title bar of menus.  This type is needed to make sure that the
menus redraw correctly.  The Resource Construction Set automatically
handles inserting \verb"G_TITLEs", so you will seldom use them directly.

   In a resource, the \verb"OB_SPEC" for all string objects is a long
pointer to a null terminated ASCII string.  The string data in the C
file is shown in the BYTE array {\tt rs\_strings}.  Again you will notice
that  the \verb"OB_SPECs" in the C file have been converted to indices into
{\tt rs\_string}. To find the string which matches the object, take the
value of \verb"OB_SPEC" and count down that many lines in {\tt rs\_strings}.
The next line is the correct string.

   The formatted text object types are \verb"G_TEXT", \verb"G_BOXTEXT", \verb"G_FTEXT",
and \verb"G_FBOXTEXT".  \verb"G_TEXTs" are a lot like strings, except that you can
specify a color, different sizes, and a positioning rule for the
text.   Since they require more memory than \verb"G_STRINGs", \verb"G_TEXTs" should
be used  sparingly to draw attention to important information within
a dialog.   \verb"G_TEXTs" are also useful for automatic centering of dialog
text which is  changed at run-time.  I will describe this technique
in detail later on.

   The \verb"G_BOXTEXT" type adds a solid background and border to the
\verb"G_TEXT" type.  These objects are occasionally used in place of
\verb"G_BUTTONs" when their color will draw attention to an important
object.

   The \verb"G_FTEXT" object is an editable text field.  You are able to
specify a constant "template" of characters, a validation field for
those characters which are to be typed in, and an initial value for
the input characters.  You may also select color, size, and
positioning rule for \verb"G_FTEXTs".  We'll discuss text editing at length
below.

   The \verb"G_FBOXTEXT" object, as you might suspect, is the same as
\verb"G_FTEXT" with the addition of background and border.  This type is
seldom used: the extra appearance details distract attention from the
text being edited.

   The \verb"OB_SPEC" for a formatted text object is a pointer to yet
another type of structure: a \verb"TEDINFO".  In the C file, you will find
these in {\tt rs\_tedinfo}.  Take the \verb"OB_SPEC" value from each text type
object and count down that many entries in {\tt rs\_tedinfo}, finding the
matching \verb"TEDINFO" on the next line.  Each contains pointers to ASCII
strings for the template, validation, and initialization.  You can
find these strings in {\tt rs\_strings}, just as above.

   There are also fields for the optional background and border
details, and for the length of the template and text.  As we will see
when discussing  editing, the most important \verb"TEDINFO" fields are the
\verb"TE_PTEXT" pointer to  initialized text and the \verb"TE_TXTLEN" field which
gives its length.

   The \verb"G_IMAGE" object type is the only one of its kind.  A \verb"G_IMAGE" is
a monochrome bit image.  For examples, see the images within the
various GEM alert boxes.  Note that monochrome does not necessarily
mean black.  The image may be any color, but all parts of it are the
SAME color.  \verb"G_IMAGEs" are used as visual cues in dialogs.  They are
seldom used as selectable items because their entire rectangle is
inverted when they are clicked.  This effect is seldom visually
pleasing, particularly if the image is colored.

   \verb"G_IMAGE" objects have an \verb"OB_SPEC" which is a pointer to a further
structure type: the \verb"BITBLK".  By now, you should guess that you will
find it in the C file in the array {\tt rs\_bitblk}.  The \verb"BITBLK" contains
fields describing the height and width of the image in pixels, its
color, and it also contains a long pointer to the actual bits which
make up the image.  In the C file, the images are encoded as
hexadecimal words and stored in arrays named IMAG0, IMAG1, and so on.

   The last type of object is the \verb"G_ICON".  Like the \verb"G_IMAGE", the
\verb"G_ICON" is a bit image, but it adds a mask array which selects what
portions of the image will be drawn, as well as an explanatory text
field.  A \verb"G_ICON" may also specify different colors for its
"foreground" pixels (the ones that are normally black), and its
"background" pixels (which are normally white).

   The pictures which you see in Desktop windows are \verb"G_ICONs", and so
are the disks and trashcan on the desktop surface.  With the latter
you will notice the effects of the mask.  The desktop shows through
right up to the edge of the \verb"G_ICON", and only the icon itself (not a
rectangle) is inverted when a disk is selected.

   The \verb"OB_SPEC" of an icon points to another structure called an
\verb"ICONBLK".  It is shown in the C file as {\tt rs\_iconblk}.  The \verb"ICONBLK"\/
contains long pointers to its foreground bit array, to the mask bit
array, and to the ASCII string of explanatory text.  It also has the
foreground and background colors as well as the location of the text
area from the  upper left of the icon.  The most common use of
\verb"G_ICONs" and \verb"ICONBLKs"  is not in dialogs, instead they are used
frequently in trees which are build at run-time, such as Desktop
windows.  In an upcoming chapter, we will return to a discussion of
building such "on-the-fly" trees with \verb"G_ICONs".

   Now, let's recap the hierarchy of resource structures:  The
highest level structures are the resource header, and then the tree
index.  The tree index points to the beginning of each object tree.
The objects making up the tree are of several types, and depending on
that type, they may contain pointers to ASCII strings, or to \verb"TEDINFO",
\verb"ICONBLK", or \verb"BITBLK" structures.  \verb"TEDINFOs" contain further pointers to
strings; \verb"BITBLKs" have pointers to bit images; and \verb"ICONBLKs" have both.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Putting it to work}

  The most common situations requiring you to
understand resource structures involve the use of text and editable
text objects in dialogs.  We'll look at two such techniques.

   Often an application requires two or more dialogs which are very
similar except for one or two title lines.  In this circumstance, you
can save a good deal of resource space by building only one dialog,
and changing the title at run time.

   It is easy to go wrong with this practice, however, because the
obvious tactic of using a \verb"G_STRING" and writing over its text at run
time can go wrong.  The first problem is that you must know in
advance the longest title to be used, and put a string that long into
the resource. If you don't you will damage other objects in the
resource as you copy in characters.  The other problem is that a
\verb"G_STRING" is always drawn at the same place in a dialog.  If the
length of the title changes from time to time, the dialog will have
an unbalanced and sloppy  appearance.

   A better way to do this is to exploit the \verb"G_TEXT" object type, and
the \verb"TEDINFO" structure.  The \verb"set_text()" routine in {\tt GEMCL04.C}
 shows
how.  The parameters provided are the tree address, the object
number, and the 32-bit address of the string to be substituted.  For
this to work, the object referenced should be defined as a \verb"G_TEXT"
type object.   Additionally, the Centered text type should be chosen,
and the object should have been "stretched" so that it fills the
dialog box from side to side.

   In the code, the first action is to get the \verb"OB_SPEC" from the
object which was referenced.  Since we know that the object is a
\verb"G_TEXT", the \verb"OB_SPEC" must point to a \verb"TEDINFO".  We need to change two
fields in the \verb"TEDINFO".  The \verb"TE_PTEXT" field is the pointer to the
actual string to be displayed; we replace it with the address of our
new string. The \verb"TE_TXTLEN" field is loaded with the new string's
length.  Since the Centered attribute was specified for the object,
changing the \verb"TE_TXTLEN" will cause the string to be correctly
positioned in the middle of the dialog!

   Editing text also requires working with the \verb"TEDINFO" structure. One
way of doing this is shown in the example.  The object to be used
(EDITOBJ) is assumed to be a \verb"G_FTEXT" or \verb"G_FBOXTEXT".  Since we will
replace the initialized text at run time, that field may be left
empty when building the object in the RCS.

   The basic trick of this code is to point the \verb"TEDINFO"'s \verb"TE_PTEXT" at
a string which is defined in your code's local stack.  The advantages
of this technique are that you save resource space, save static data
by putting the string in reusable stack memory, and automatically
create a scratch string which may be discarded if the dialog is
cancelled.

   The text string shown is arbitrarily 41 characters long.  You
should give yours a length equal to the number of blanks in the
object's template field plus one.  Note that the code is shown as a
segment,  rather than a subroutine.  This is required because the
text string must be allocated within the context of dialog handling
routine itself,  rather than a routine which it calls!

   After the tree address is found, the code proceeds to find the
\verb"TEDINFO" and modify its \verb"TE_PTEXT" as described above.  However, the
length which is inserted into \verb"TE_TXTLEN" must be the maximum string
length,  including the null!

   The final line of code inserts a null into the first character of
the uninitialized string.  This will produce an empty editing field
when the dialog is displayed.  If there is an existing value for  the
object, you should instead use \verb"strcpy()" to move it into \verb"text[]". Once
the dialog is complete, you should check its final status as
described in the last section. If an "OK" button was clicked, you
will then use \verb"strcpy()" to move the value in \verb"text[]" back to its static
location.

   Although I prefer this method of handling editable text, another
method deserves mention also.  This procedure allocates a full length
text string of blanks when creating the editable object in the RCS.
At  run-time, the \verb"TE_PTEXT" link is followed to find this string's
location in  the resource, and any pre-existing value is copied in.
After the dialog is run, the resulting value is copied back out if
the dialog completed successfully.

   Note that in both editing techniques a copy of the current string
value is kept within the application's data area.  Threading the
resource whenever you need to check a string's value is extremely
wasteful.

   The validation string normally contains the same character repeated
a great many times. Fortunately that is not necessary. AES duplicates
the last character of the string as often as it is needed.

   All masks except 'X', 'a' and 'n' convert valid characters to
uppercase. Unfortunately foreign characters are not converted when using
the 'f' or 'F' masks.

\begin{description}
\item[X] all characters
\item[x] all characters are converted to uppercase
\item[9] 0..9
\item[A] A..Z, foreign characters
\item[a] a..z A..Z foreign characters
\item[N] A..Z 0..9
\item[n] a..z 0..9 A..z foreign characters
\item[P] 0..9 A..Z foreign characters \verb"\ ? * : . _" 
\item[p] 0..9 A..Z foreign characters \verb"\ : . _"
\item[F] a..z 0..9 A..Z foreign characters \verb": ? * _" (no '.' but ':')
\item[f] a..z 0..9 A..Z foreign characters \verb"_" (no '.')
\end{description}

   One final note on editable text objects:  GEM's editor uses the
commercial at sign '\verb"@"' as a "meta-character".  If it is the first
byte of the initialized text, then the field is displayed blank no
matter what follows.  This can be useful, but is sometimes confusing
when a user in all innocence enters an \verb"@" and has his text disappear
the next time the dialog is drawn!


% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Back to an omission}

     So, we established that resources trees are
pointed to by the tree index, and that they are composed of objects
which contain pointers onward to other structures.  However, we
passed over the issue of linkage among the objects within a tree.  It
is now time to go back and cure this omission.

     The technical term for the linkage scheme of an object tree is a
"right-threaded binary tree".   If you already know what this is, you
can skim over the next few paragraphs.  If you happen to have access
to a copy of the book "FUNDAMENTAL ALGORITHMS", which is part of the
series THE ART OF COMPUTER PROGRAMMING by Donald E. Knuth, you might
want to read his excellent discussion of binary trees beginning on
page 332.

     For the following discussion, you should have a listing of the C
image of a resource tree in front of you.  Before we begin, I should warn you of one
peculiarity of "computer trees":  They grow upside-down!  That is,
when they are diagrammed or described, their root is at the top, and
the  "leaves" grow downward.  You will see this both in the listing,
and in the way the following discussion talks about moving through
trees.

     Each GEM object tree begins at its ROOT object, numbered zero,
which is the object pointed at by the tree index.  There are three
link  fields at the beginning of each object.  They are called
\verb"OB_NEXT", \verb"OB_HEAD",  and \verb"OB_TAIL", which is the order in which they
appear.

     Each of the links is shown as an index relative to the root of
the current tree.  This means that the link '0' would refer to the
root of the tree, while '2' would indicate the object two lines below
it. The special link -1 is called NIL, and means that there is no
link in  the given direction.

     Each object, or node, in a tree may have "offspring" or nodes
which are nested below it.  If it does, then its \verb"OB_HEAD" will point
to its first (or "leftmost") "child", while the \verb"OB_TAIL" will point to
the last ("rightmost") of its offspring.  The \verb"OB_NEXT" pointer links
the  children together, with the \verb"OB_NEXT" of the first pointing to the
second, and so on, until the \verb"OB_NEXT" of the last finally points back
to its parent, the object at which we started.

     Remember that each of these children may in turn have offspring
of their own, so that the original "parent" may have a large and
complex collection of "descendents".

     Let's look at the first tree in the listing to see an example
of this structure.  The very first object is the ROOT.  Note that its
\verb"OB_NEXT" is NIL, meaning that there are no more objects in the tree:
the ROOT is both the beginning and the end of the tree.  In this
case, the \verb"OB_HEAD" is 1 and the \verb"OB_TAIL" is 3, showing that there are
at least two different children.

     Following \verb"OB_HEAD" down to the next line, we can trace through
the \verb"OB_NEXT" links (2, 3, 0) as they lead through a total of three
children and back to the ROOT.  You will notice that the first two
children have NIL for the \verb"OB_HEAD" and \verb"OB_TAILs", indicating that they
have no further offspring.

     However, node three, the last child of the ROOT, does have the
value 4 for both its \verb"OB_HEAD" and \verb"OB_TAIL".  By this we can tell that
it  has one, and only one, offspring.  Sure enough, when we look at
node four, we see that its \verb"OB_NEXT" leads immediately back to node
three. Additionally, it has no further offspring because its \verb"OB_HEAD"
and \verb"OB_TAIL" are NIL.

     You will find that object trees are always written out by the
Resource Construction Set in "pre-order".  (Again, see Knuth if you
have a copy.)  This means that the ROOT is always written first, then
its offspring left to right.  This rule is applied recursively, that
is, we go down to the next level and write out each of these nodes,
then THEIR children left to right, and so on.

     For a further example, look at the next tree in \verb"rs_object" in the
listing.  You will see that the ROOT has an \verb"OB_HEAD" of 1 and an
\verb"OB_TAIL" of 6, but that it actually has only three offspring (nodes 1,
2 and 6).  We see that node 2 itself had children, and applying the
rule given above, they were written out before continuing with the
next child of the ROOT.

     Why was this seemingly complex structure chosen for GEM?  The
reason has do with the tasks of drawing objects in their proper
locations on the screen, and determining which object was "hit" when
a mouse click is detected.

     To find out how this works, we must look at four more fields
found in each object: \verb"OB_X", \verb"OB_Y", \verb"OB_WIDTH", and \verb"OB_HEIGHT".  These
fields are the last four on each line in the sample trees.

     Each object in a tree "owns" a rectangle on the screen.  These
fields define that rectangle.  When a resource is stored "outside"
the  program the fields are in character units, so that an object
with \verb"OB_WIDTH"  of 10 and \verb"OB_HEIGHT" of 2 (for instance) would define a
screen area 10  characters wide and 2 high.

     When the resource is read into memory with an \verb"rsrc_load" call,
GEM multiplies the appropriate character dimension in pixels into
each of these fields.  In this way portability is achieved: the same
resource file works for any of the ST's three resolutions.  Knowing
how \verb"rsrc_load" works, your code should treat these fields as pixel
coordinates.

     (I have committed one oversimplification above.  If an object is
not created on a character boundary in the RCS, then the external
storage method described will not work.  In this case, the lower byte
of each rectangle field is used to store the nearest character
position, while the upper byte stores the pixel remainder to be added
after the character size is multiplied in.

     Non-character-boundary objects may only be created in the "FREE"
tree mode of the Resource Construction Set (also called "PANEL" in
RCS 2.0). You should use them only in programs which will run in a
single ST screen  mode, because pixel coordinates are not portable
between resolutions.

     There is a bug in AES that may cause some problems: when \verb"rsrc_load"
or \verb"rsrc_obfix" convert from pixel to character coordinates, they
check for an \verb"OB_WIDTH" value of 80 characters and set the pixelwidth
to the screenwidth. On a monitor that can display more than 80 characters
in a row, an object of 80 characters can actually be larger than an object
of 90 characters! That's because if no value of 80 is found, AES multiplies
the value with the character size. Then the pixel offset from the high byte
is added.)

     The first real secret of object rectangles is that each \verb"OB_X" and
\verb"OB_Y" is specified RELATIVE to the X and Y coordinate of its parent
object  within the tree.  This is the first property we have seen
that is actually "inherited" from level to level within the tree.

     The second secret is more subtle:  Every object's rectangle must
be entirely contained within the rectangle of its parent.  This
principle goes by the names "bounding rectangles" or "visual
hierarchy".  We'll see in a moment how useful it is when detecting
mouse/object collisions.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{How GEM does it}

     Knowing these secrets, and the linkage structure  of object
trees, we can deduce how a number of the GEM operations must work.
For instance, consider \verb"objc_offset",  which returns the actual screen
X and Y  of an object.  We can see now that simply loading the \verb"OB_X"
and \verb"OB_Y" fields of  the object does not suffice: they only give the
offset relative to the parent  object.  So, \verb"objc_offset" must BEGIN
with these values, and then work its way  back up to the ROOT of the
tree, adding in the offsets found at each level.

     This can be done by following the \verb"OB_NEXT" links from the chosen
object.  Whenever \verb"OB_NEXT" points to an object whose \verb"OB_TAIL" points
right back  to the same location, then the new node is another level,
or "parent" in the  tree, and \verb"objc_offset" adds its \verb"OB_X" and \verb"OB_Y" into
the running totals.  When \verb"OB_NEXT" becomes NIL, then the ROOT has been
reached and the totals are the values to return.  (By the way,
remember that the \verb"OB_X" and \verb"OB_Y" of the ROOT are undefined until
\verb"form_center" has been called for the tree.  They are shown as zeroes
in the sample trees.)

     We can also figure out \verb"objc_draw".  It works its way DOWN the
tree, drawing each object as it comes to it.  It, too, must keep a
running X and Y variable, adding in object offsets as it descends
tree levels (using \verb"OB_HEAD"), and subtracting them again as it returns
from each level.   Since the larger objects are nearer the ROOT, we
can now see why they are drawn first, with smaller objects drawn
later or "on top of" them.

     (If you write an application which needs to move portions of a
dialog or screen with respect to each other, you can take advantage
of inheritance of screen position in \verb"objc_draw".  Simply by changing
the \verb"OB_X" and/or \verb"OB_Y" of an object, you can move it and its entire
sub-tree to a new location in the dialog.  For instance, changing the
coordinates of the parent box of a set of radio buttons will cause
all of the buttons to move along with it.)

     \verb"Objc_draw" also gives us an example of the uses of visual
hierarchy. Recall that a clipping rectangle is specified when calling
\verb"objc_draw". At each level of the tree we know that all objects below
are contained in the screen rectangle of the current object.  If the
current rectangle falls completely outside the specified clipping
rectangle, we know  immediately that we need not draw the object, or
any of its descendents! This ability to ignore an entire subtree is
called "trivial rejection".

     Now it's rather easy to figure out \verb"objc_find".  It starts out by
setting its "object found" variable to NIL.  It begins a "walk"
through the entire object tree, following \verb"OB_HEAD" and \verb"OB_NEXT" links,
and keeping  a current X and Y, just like \verb"objc_draw".

     At each node visited, it simply checks to see if the "mouse" X,Y
specified in the call are inside the current object's rectangle.  If
they  are, that object becomes the found object, and the tree walk
continues with the object's offspring, and then siblings.  Notice how
this checking of offspring makes sure that a smaller object nested
within, i.e., below, a larger object is found correctly.

     If the mouse X,Y position is not within the object being
checked, then by visual hierarchy it cannot be within any of its
offspring, either.   Trivial rejection wins again, and the entire
sub-tree is skipped!  \verb"Objc_find"  moves on to the \verb"OB_NEXT" of the
rejected object.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Thought Experiments}

     Thinking about the \verb"objc_find" algorithm  reveals some information
about its performance, and a few tricks we may  use in improving the
appearance of dialogs and other object trees.

     First consider the problem of a dialog which contains many
objects. If we lay them all out "side-by-side", then they will all be
immediate offspring of the ROOT object.  In this situation, the
trivial rejection method will gain nothing.  The time \verb"objc_find" takes
to complete will vary linearly with the total number of objects.
This is called an "Order N" process.

     Suppose that instead we broke up the dialog into two areas with
invisible boxes, then broke up each of these areas in a like fashion,
and so on until we got down to the size of the individual selectable
objects.  The number of bottom level objects in this scheme is a
power  of two equal to the depth of the tree. Trivial rejection is
used to its  fullest in this case.  It is called an "Order Log N"
process, and is much  more efficient for large numbers of objects.

     In practice, the speed of the ST will allow you to ignore this
distinction for most dialogs and other trees.  But if you get into a
situation when speed is critical in searching a large tree, remember
that nesting objects can improve performance dramatically.

     If you have been following closely, you may have also noticed a
hole in the visual hierarchy rule.  It says that all of a node's
children must lie within its rectangle, but it does NOT guarantee
that the children's  rectangles will be disjoint, that is, not
overlap one another.  This peculiarity is the basis of several useful
tricks.

     First, remember that \verb"objc_find" always tries to scan the entire
tree.  That is, it doesn't quit when it finds the first object on the
given coordinates.  As mentioned above, this normally guarantees that
nested objects will be found.  Consider, however, what happens when
the mouse  coordinates are on a point where two or more objects {\em at
the same level }\/ overlap: they will replace one another as the "found
object" until  \verb"objc_find" returns with the one which is "last", that
is, rightmost in  the tree.

     This quirk can be used to advantage in a number of cases.
Suppose that you have in a dialog an image and a string which you
would  like to be selected together when either is clicked.  Nesting
within a common parent achieves nothing in this case.  Instead,
knowing that  \verb"form_do" must use \verb"objc_find", you could use our trick.

     You have to know that the Resource Construction Set normally
adds  objects in a tree left to right, in the order in which you
inserted them.  You proceed to build the dialog in the following
order: insert the image  first, the string next, then carefully add
an invisible box which is not  nested within either, and size it to
cover them both.  Set the \verb"SELECTABLE" attribute for the box, and the
dialog manager will find it, and invert  the whole area, when either
the image or string is clicked.

     By the way, remember that the SORT option in the RCS will change
the order of an object's offspring.  If you are going to try this
trick, don't use SORT!  It will undo all of your careful work.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{A treewalker of our own}

     Since the GEM system gets so much mileage  out of walking object
trees, it seems reasonable that the same method should  be useful in
application programs.  In the {\tt GEMCL05.C} you will find \verb"map_tree()". As
many LISP veterans might guess from the name, this code will traverse
all or part of an object tree, applying a function to each node.  It
also allows the function to return a true/false value specifying
whether  the sub-tree below a particular node should be ignored.
Let's examine \verb"map_tree()" in more detail as a final review of object
tree structure.

     First, look at the parameters.  "tree" is the long address of
the object tree of interest, as retrieved by \verb"rsrc_gaddr".  "this" is
the node at which to begin the traverse, and "last" is the node at
which to terminate.

     In most cases, the beginning node will be ROOT, and the final
value will be NIL.  This will result in the entire tree being
traversed. You may use other values, but be sure that you CAN get to
"last" from "this" by following tree links!  Although \verb"map_tree()"
includes a safety  check to prevent "running off" the tree, you could
get some very strange  results from incorrect parameters.

     The declaration for the final parameter, "routine", makes use of
C construct which may be new to some.  It is a pointer to a
subroutine which returns a WORD as a result.

     \verb"Map_tree()" begins by initializing a temporary variable, {\tt tmp1},
which is used to store the number of the last node visited.  Since no
node will follow itself, setting {\tt tmp1}\/ to the starting node is safe.

     The main loop of the routine simply repeats visiting a new node
until the last value is reached, or the safety check for end of tree
is satisfied.

     At any node visited, we can be in one of two conditions. Either
we are at a node which is "new", that is, not previously visited, or
else we are returning to a parent node which has already been
processed. We can detect the latter condition by comparing the last
node visited (tmp1) with the \verb"OB_TAIL" pointer of the current node.  If
the node is "old", it is not processed a second time, we simply
update tmp1 and  continue.

     If the node is new, we call "routine" to process it, sending the
tree address and object number as parameters.  If a FALSE is
returned,  we will ignore any subtree below this node.  On a TRUE
return, we load up  the \verb"OB_HEAD" pointer and follow it if a subtree
exists.  (If you don't care  about rejecting subtrees, simply remove
the if condition.)  Finally, if  the new node had no subtree, or was
rejected by "routine", we follow along  its \verb"OB_NEXT" link to the next
node.

     A simple application of our new tool shows its power. 
You may recall the tedium of deselecting every button
inside a dialog after it was completed.  Using \verb"map_tree()", you can
deselect EVERY OBJECT in the tree by using:

\verb"map_tree(tree, ROOT, NIL, desel_obj);"

You must use a slightly modified version of \verb"desel_obj()"
which always returns TRUE.  Be sure to
define or declare \verb"desel_obj()" in your code BEFORE making the \verb"map_tree"
call!

     In the next chapters, I will return to \verb"map_tree()" and show how it
can be used for advanced techniques such as animated dialogs.

\newpage

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\section{Raster operations}

    This chapter of  ST Professional GEM is devoted to
explaining the raster, or "bit-blit" portion of the Atari ST's VDI
functions.

     Please note that this is NOT an attempt to show how to write
directly to the video memory, although you will be able to deduce a
great deal from the discussion. As usual, there is a listing to demonstrate
the topics discussed under the name of {\tt GEMCL06.C}.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Defining terms}

     To understand VDI raster operations, you need  to understand the
jargon used to describe them.  (Many programmers will be tempted to
skip this section and go directly to the code.  Please don't do it
this time:  Learning the jargon is the larger half of understanding
the raster operations!)

     In VDI terms a {\tt raster area}\/ is simply a chunk of contiguous words
of memory, defining a bit image.  This chunk is called a "form".  A
form  may reside in the ST's video map area or it may be in the data
area of  your application.  Forms are roughly analogous to "blits" or
"sprites"  on other systems.  (Note, however, that there is no sprite
hardware on the ST.)

     Unlike other systems, there is NO predefined organization of the
raster form.  Instead, you determine the internal layout of the form
with an auxiliary data structure called the \verb"MFDB", or Memory Form
Definition Block.  Before going into the details of the \verb"MFDB", we need
to look at the various format options.  Their distinguishing features
are monochrome vs.~color, standard vs.~device-specific and even-word
vs.~fringed.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Monochrome vs.~Color}

     Although these terms are standard, it might be better to say
"single-color vs.~multi-color".  What we are actually defining is the
number of bits which correspond to each dot, or pixel, on the screen.
In the ST, there are three possible answers. The high-resolution mode
has one bit per pixel, because there is only one "color": white.

     In the medium resolution color mode, there are four possible
colors for each pixel.  Therefore, it takes two bits to represent
each dot on the screen.  (The actual colors which appear are
determined by  the settings of the ST's pallette registers.)

     In the low resolution color mode, sixteen colors are generated,
requiring four bits per pixel.  Notice that as the number of bits per
pixel has been doubled for each mode, so the number of pixels on the
screen has been halved: 640 by 400 for monochrome, 640 by 200 for
medium-res, and 320 by 200 by low-res.  In this way the ST always
uses  the same amount of video RAM: 32K.

     Now we have determined how many bits are needed for each pixel,
but not how they are laid out within the form.  To find this out, we
have  to see whether the form is device-dependent or not.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Standard vs.~Device-Specific Format}

     The standard raster form format is a constant layout which is
the same for all GEM systems.  A device-specific form is one which is
stored in the internal format of a particular GEM system.  Just as
the ST has three different screen modes, so it has three different
device-specific form formats.  We will look at standard form first,
then the ST-specific forms.

     First, it's reasonable to ask why a standard format is used. Its
main function is to establish a portability method between various
GEM systems.  For instance, an icon created in standard format on an
IBM PC GEM setup can be moved to the ST, or a GEM Paint picture from
an AT\&T 6300 could be loaded into the ST version of Paint.

     The standard format has some uses even if you only work with the
ST, because it gives a method of moving your application's icons and
images amongst the three different screen modes.  To be sure,  there
are limits to this.  Since there are different numbers of pixels  in
the different modes, an icon built in the high-resolution mode will
appear twice as large in low-res mode, and would appear oblong in
medium-res.  (You can see this effect in the ST Desktop's icons.)
Also,  colors defined in the lower resolutions will be useless in
monochrome.

     The standard monochrome format uses a one-bit to represent
black, and uses a zero for white.  It is assumed that the form begins
at the  upper left of the raster area, and is written a word at a
time left to right on each row, with the rows being output top to
bottom.  Within each word, the most significant bit is the left-most
on the screen.

     The standard color form uses a storage method called "color
planes". The high-order bits for all of the pixels are stored just as
for monochrome, followed by the next-lowest bit in another contiguous
block, and so on until all of the necessary color bits have been
stored.

     For example, on a 16-color system, there would be four different
planes.  The color of the upper-leftmost bit in the form would be
determined by concatenating the high-order bit in the first word of
each plane of the form.

     The system dependent form for the ST's monochrome mode is very
simple: it is identical to the standard form!  This occurs because
the  ST uses a "reverse-video" setup in monochrome mode, with the
background  set to white.

     The video organization of the ST's color modes is more
complicated. It uses an "interleaved plane" system to store the bits
which make up a pixel.  In the low-resolution mode, every four words
define the values of 16 pixels.  The high-order bits of the four
words are merged to form the left-most pixel, followed by the next
lower bit of each word, and so on.  This method is called
interleaving because the usually separate color planes described
above have been shuffled together in memory.

     The organization of the ST's medium-resolution mode is similar
to low-res, except the only two words are taken at a time.  These are
merged to create the two bits needed to address four colors.

     You should note that the actual color produced by a particular
pixel value is NOT fixed.  The ST uses a color remapping system
called a palette.  The pixel value in memory is used to address a
hardware  register in the palette which contains the actual RGB
levels to be sent to the display.  Programs may set the palette
registers with  BIOS calls, or the user may alter its settings with
the Control Panel desk accessory.  Generally, palette zero
(background) is left as white, and the highest numbered palette is
black.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Even-Word vs.~Fringes}

     A form always begins on a word boundary, and is always stored
with an integral number of words per row.  However,  it is possible
to use only a portion of the final word.  This partial word is called
a "fringe".  If, for instance, you had a form 40 pixels wide,  it
would be stored with four words per row: three whole words, and one
word with the eight pixel fringe in its upper byte.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{MFDBs}

     Now we can intelligently define the elements of the \verb"MFDB".  Its
exact C structure definition will be found in the listing. The
{\tt fd\_nplanes}\/ entry determines the color scheme: a value of one is
monochrome, more than one denotes a color form.  If {\tt fd\_stand} is zero,
then the form is device-specific, otherwise it is in standard format.

     The {\tt fd\_w}\/ and {\tt fd\_h}\/ fields contain the pixel width and height of
the form respectively.  {\tt fd\_wdwidth}\/ is the width of a row in words.
If {\tt fd\_w}\/ is not exactly equal to sixteen times {\tt fd\_wdwidth}, then the
form has a fringe.

     Finally, {\tt fd\_addr}\/ is the 32-bit memory address of the form
itself. Zero is a special value for {\tt fd\_addr}.  It denotes that this
\verb"MFDB" is for the video memory itself.  In this case, the VDI
substitutes the actual address of the screen, and it ignores ALL of
the other parameters. They are replaced with the size of the whole
screen and number of planes in the current mode, and the form is (of
course) in device-specific format.

     This implies that any \verb"MFDB" which points at the screen can only
address the entire screen.  This is not a problem, however, since the
the VDI raster calls allow you to select a rectangular region within
the form.  (A note to advanced programmers:  If this situation is
annoying, you can retrieve the address of the ST's video area from
low memory, add an appropriate offset, and substitute it into the
\verb"MFDB" yourself to address a portion of the screen.)

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Let's operate}

     Now we can look at the VDI raster operations themselves.  There
are actually three: transform form, copy raster opaque, and copy
raster transparent.  Both copy raster functions can perform a variety
of logic operatoins during the copy.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Transform Form}

     The purpose of this operation is to change the format of a form:
from standard to device-specific, or vice-versa.  The calling
sequence is:

\begin{verbatim}
     vr_trnfm(vdi_handle, source, dest);
\end{verbatim}

where {\tt source}\/ and {\tt dest}\/ are each pointers to \verb"MFDBs".  They ARE allowed
to be the same.  Transform form checks the {\tt fd\_stand}\/ flag in the
source \verb"MFDB", toggles it and writes it into the destination \verb"MFDB" after
rewriting the form itself.  Note that transform form CANNOT change
the number of color planes in a form: {\tt fd\_nplanes}\/ must be identical in
the two \verb"MFDBs".

     If you are writing an application to run on the ST only, you
will probably be able to avoid transform form entirely.  Images and
icons are stored within resources as standard forms, but since they
are monochrome, they will work "as is" with the ST.

     If you may want to move your program or picture files to another
GEM system, then you will need transform form.  Screen images can be
transformed to standard format and stored to disk.  Another system
with the same number of color planes could the read the files, and
transform the image to ITS internal format with transform form.

     A GEM application which will be moved to other systems needs to
contain code to transform the images and icons within its resource,
since standard and device-specific formats will not always coincide.

     If you are in this situation, you will find several utilities in
the listings which you can use to transform \verb"G_ICON" and \verb"G_IMAGE"
objects. There is also a routine which may be used with \verb"map_tree()"
from the  last column in order to transform all of the images and
icons in a resource tree at once.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Copy Raster Opaque}

     This operation copies all or part of the source form into the
destination form.  Both the source and destination forms must be in
device-specific form.  Copy raster opaque is for moving information
between "like" forms, that is, it can copy from monochrome to
monochrome, or between color forms with the same number of planes.
The calling format is:

\begin{verbatim}
     vro_cpyfm(vdi_handle, mode, pxy, source, dest);
\end{verbatim}

  As above, the source and dest parameters are pointers to \verb"MFDBs"
(which in turn point to the actual forms).  The two \verb"MFDBs" may point
to memory areas  which overlap.  In this case, the VDI will perform
the move in a  non-destructive order.  Mode determines how the pixel
values in the source and destination areas will be combined.  I will
discuss it separately later on.

     The pxy parameter is a pointer to an eight-word integer array.
This array defines the area within each form which will be affected.
\verb"Pxy[0]" and \verb"pxy[1]" contain, respectively, the X and Y coordinates of
the upper left corner of the source rectangle.  These are given as
positive  pixel displacements from the upper left of the form.
\verb"Pxy[2]" and \verb"pxy[3]"  contain the X and Y displacements for the lower
right of the source rectangle.

     \verb"Pxy[4]" through \verb"pxy[7]" contain the destination rectangle in the
same format.  Normally, the destination and source should be the same
size.  If not, the size given for the source rules, and the whole are
is transferred beginning at the upper left given for the destination.

     This all sounds complex, but is quite simple in many cases.
Consider an example where you want to move a 32 by 32 pixel area
from one part of the display to another.  You would need to allocate
only one \verb"MFDB", with a zero in the {\tt fd\_addr}\/ field.  The VDI will take
care of counting color planes and so on.  The upper left raster
coordinates of the source and destination rectangles go into \verb"pxy[0]",
\verb"pxy[1]" and \verb"pxy[4]", \verb"pxy[5]" respectively.  You add 32 to each of these
values and insert the results in the corresponding lower right
entries, then make the copy call using the same \verb"MFDB" for both source
and destination.  The VDI takes care of any overlaps.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Copy Raster Transparent}

     This operation is used for copying from a monochrome form to a
color form.  It is called transparent because it "writes through" to
all of the color planes.  Again, the forms need to be in
device-specific form.  The calling format is:

\begin{verbatim}
     vrt_cpyfm(vdi_handle, mode, pxy, source, dest, color);
\end{verbatim}

  All of the parameters are the same as copy opaque, except that
color has been added.  Color is a pointer to a two word integer
array. \verb"Color[0]" contains the color index which will be used when a
one appears in the source form, and \verb"color[1]" contains the index for
use when a zero occurs.

     Incidentally, copy transparent is used by the AES to draw
\verb"G_ICONs" and \verb"G_IMAGEs" onto the screen.  This explains why you do not
need to convert them to color forms yourself.

     (A note for advanced VDI programmers: The pxy parameter in both
copy opaque and transparent may be given in normalized device
coordinates (NDC) if the workstation associated with {\tt vdi\_handle}\/ was
opened for NDC work.)

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{The Mode Parameter}

     The {\tt mode}\/ variable used in both of the copy functions is an
integer with a value between zero and fifteen. It is used to select
how the copy function will merge the pixel values of the source and
destination forms.  The complete table of functions is given in the
listings.  Since a number of these are of obscure or questionable
usefulness, I will only discuss the most commonly used modes.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Replace Mode}

     A mode of 3 results in a straight-forward copy: every
destination pixel is replaced with the corresponding source form
value.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Erase Mode}

     A mode value of 4 will erase every destination pixel which
corresponds to a one in the source form.  (This mode corresponds to
the "eraser" in a Paint program.)  A mode value of 1 will erase every
destination pixel which DOES NOT correspond to a one in the source.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{XOR Mode}

     A mode value of 6 will cause the destination pixel to be toggled
if the corresponding source bit is a one. This operation is
invertable, that is, executing it again will reverse the effects.
For this reason it is often used for "software sprites" which must be
shown and then removed from the screens.  There are some problems
with this in color operations, though - see below.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Transparent Mode}

     Don't confuse this term with the copy  transparent function
itself.  In this case it simply means that ONLY  those destination
pixels corresponding with ones in the source form will  be modified
by the operation.  If a copy transparent is being performed, the
value of \verb"color[0]" is substituted for each one bit in the source form.
A mode value of 7 selects transparent mode.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Reverse Transparent Mode}

     This is like transparent mode except that only those destination
pixels corresponding to source ZEROS are modified.  In a copy
transparent, the value of \verb"color[1]" is substituted for each zero bit.
Mode 13 selects reverse transparent.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{The problem of color}

     I have discussed the various modes as if they deal with one and
zero pixel values only.  This is exactly true when both forms are
monochrome, but is more complex when one or both are color forms.

     When both forms are color, indicating that a copy opaque is
being performed, then the color planes are combined bit-by-bit using
the rule for that mode.  That is, for each corresponding source and
destination pixel, the VDI extracts the top order bits and processes
them, then operates on the next lower bit, and so on, stuffing each
bit back into the destination form as the copy progresses.  For
example, an XOR operation on pixels valued 7 and 10 would result in a
pixel value of 13.

     In the case of a copy transparent, the situation is more
complex. The source form consists of one plane, and the destination
form has two  or more.  In order to match these up, the \verb"color[]" array
is used.  Whenever a one pixel is found, the value of \verb"color[0]" is
extracted and used in the bit-by-bit merge process described in the
last paragraph.  When a zero is found, the value of \verb"color[1]" is
merged into the destination form.

     As you can probably see, a raster copy using a mode which
combines the source and destination can be quite complex when color
planes are used!  The situation is compounded on the ST, since the
actual color values may be remapped by the palette at any time.   In
many cases, just using black and white in \verb"color[]" may achieve the
effects you desire.  If need to use full color, experimentation is
the  best guide to what looks good on the screen and what is garish
or  illegible.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Optimizing raster operations}

     Because the VDI raster functions are extremely generalized, they
are also slower than hand-coded screen drivers which you might write
for your own special cases.  If you want to speed up your
application's raster operations without writing assembly language
drivers, the following hints will help you increase the VDI's
performance.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Avoid merged copies}

     These are copy modes, such as XOR,  which  require that words be
read from the destination form.  This extra memory access increases
the running time by up to fifty percent.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Move to corresponding pixels}

     The bit position within a word of the destination rectangle
should correspond with the bit position of the source rectangle's
left edge.  For instance, if the source's left edge is one pixel in,
then the destination's edge could be at one, seventeen, thirty-three,
and so.  Copies which do not obey this rule force the VDI to shift
each word of the form as it is moved.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Avoid fringes}

     Put the left edge of the source and destination  rectangles on
an even word boundary, and make their widths even multiples  of
sixteen.  The VDI then does not have to load and modify partial words
within the destination forms.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Use another method}

     Sometimes a raster operation is not the fastest way to
accomplish your task.  For instance, filling a rectangle with zeros
or ones may be accomplished by using raster copy modes zero and
fifteen, but it is faster to use the VDI \verb"v_bar" function instead.
Likewise, inverting an area on the screen may be done more quickly
with \verb"v_bar" by using BLACK in XOR mode.  Unfortunately, \verb"v_bar" cannot
affect  memory which is not in the video map, so these alternatives
do not always work.


\newpage

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\section{Menu Structures}

In this chapter,
I will be discussing GEM menu structures and how to use them
in your application.  You will find the demonstration file containing
the code for this chapter in the listing {\tt GEMCL07.C}.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Menu Basics}

  In ST GEM, the menu consists of a bar
across the top of the screen which displays several sub-menu
titles.  Touching one of the titles causes it to highlight,
and an associated "drop-down" to be drawn  directly below on
the screen.  This drop-down may be dismissed by moving  to
another title, or by clicking the mouse off of the drop-down.


    To make a selection, the mouse is moved over the
drop-down.  Each  valid selection is highlighted when the
mouse touches it.  Clicking the mouse  while over one of
these selections picks that item.  GEM then undraws the
drop-down, and sends a message to your application giving the
object number  of the title bar entry, and the object number
of the drop-down item which  were selected by the user.  The
selected title entry is left highlighted  while your code
processes the request.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Menu Structures}

    The data structure which defines a GEM
menu is (surprise!) an object tree, just like the dialogs and
panels which we have discussed before.  However, the
operations of the GEM menu manager are quite different from
those of the form manager, so the internal design of the menu
tree has some curious constraints.

    The best way to understand these constraints is to look
at an  example.  The first item in the listing is the object
structure (only) of the menu tree from the GEM Doodle/Demo
sample application.

    The ROOT of a menu tree is sized to fit the entire
screen.  To satisfy the visual hierarchy principle the screen
is divided into two parts: \verb"THE BAR",
containing the menu titles, and \verb"THE SCREEN", while contains
the drop-downs when they are drawn.  Each of these areas is
defined by an object of the same name, which are the only two
objects linked directly below the ROOT of a menu tree.  You
will notice an important implication of this structure:  The
menu titles and their associated drop-downs are stored in
entirely different subtrees of the menu!

    While examining \verb"THE BAR" in the example listing, you may
notice that its \verb"OB_HEIGHT" is very large (513).  In
hexadecimal this is 0x0201.  This defines a height for \verb"THE BAR"
of one character plus two pixels used for spacing.  \verb"THE BAR"
 and its subtree are the only objects which are drawn on
the screen in the menu's quiescent state.

    The only offspring object of \verb"THE BAR" is \verb"THE ACTIVE".  This
object defines the part of \verb"THE BAR" which is covered by menu
titles.  The screen rectangle belonging to \verb"THE ACTIVE" is used
by the GEM screen manager when it  waits for the mouse to
enter an active menu title.  Notice that \verb"THE ACTIVE" and its
offspring also have \verb"OB_HEIGHTs" with pixel residues.

    The actual menu titles are linked left to right in order
below \verb"THE ACTIVE".  Their \verb"OB_Xs" and \verb"OB_WIDTHs" 
are arranged so that they  completely cover \verb"THE ACTIVE".  
Normally, the title objects are typed  \verb"G_TITLE", a special 
type which assures that the title bar margins are correctly drawn.

    \verb"THE SCREEN" is the parent object of the drop-down boxes
themselves. They are linked left to right in an order
identical with their titles, so  that the menu manager can
make the correct correspondence at run-time.  The \verb"OB_X" of
each drop-down is set so that it is positioned below its
title on the screen.

    Notice that it is safe to overlap the drop-downs within a
menu,  since only one of them will be displayed at any time.
There is one constraint on the boxes however:  They must be
no greater than a quarter screen in total size.  This is the
size of the off-screen blit buffer which is used by GEM to
store the screen contents when the drop-down is drawn.  If
you exceed this size, not all the screen under the drop-down
will be restored, or the ST may crash!

    The entries within a drop-down are usually \verb"G_STRINGs",
which are optimized for drawing speed.  The rectangles of
these entries must  completely cover the drop-down, or the
entire drop-down will be inverted  when the mouse touches an
uncovered area!  Techniques for using objects  other than
\verb"G_STRINGs" are discussed later on.

    The first title and its corresponding drop-down are
special.  The title name, by custom, is set to DESK.  The
drop-down must contain exactly  eight \verb"G_STRING" objects.  The
first (again by custom) is the INFO entry,  which usually
leads to a dialog displaying author and copyright information
for your application.  The next is a separator string of
dashes with the \verb"DISABLED" flag set.  The following six objects
are dummy strings which GEM fills in with the names of desk
accessories when your menu is loaded.

    The purpose of this description of menu trees is to give
you an understanding of what lies "behind the scenes" in the
next section, which describes the run-time menu library
calls.  In practice, the Resource Construction Set provides
"blank menus" which include all of the required elements, and
it also enforces the constraints on internal structure.  You
only need to worry about these if you modify the menu tree
"on-the-fly".

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Using the menu}

Once you have loaded the application's
resource, you can ask the AES to install your menu.  You must
first get the address of the menu tree within the resource
using:

\begin{verbatim}
    rsrc_gaddr(R_TREE, MENUTREE, &ad_menu);
\end{verbatim}

 assuming that \verb"MENUTREE" is the name you gave the menu in the
RCS, and that {\tt ad\_menu} is a LONG which will receive the
address.  Then you call the AES to establish the menu:

\begin{verbatim}
    menu_bar(ad_menu, TRUE);
\end{verbatim}

 At this point, the AES draws your menu bar on the screen and
animates it when the user moves the mouse into the title
area.

    The AES indicates that the user has made a menu selection
by sending your application a message.  The message type is
\verb"MN_SELECTED",  which will be stored in \verb"msg[0]", the first
location in the message  returned by \verb"evnt_multi()".

    The AES also stores the object number of the selected
menu's  title in \verb"msg[3]", and the object number of the
selected menu item in \verb"msg[4]".  Generally, your application
will process menu messages with nested C switch statements.
The outer switch will have one case for each menu title, and
the inner switch statements will have a case for each entry
within the selected menu.  (This implies that you must give a
name to each title and to each menu entry when you create the
menu in the RCS.)

    After the user has made a menu selection, the AES leaves
the title of the chosen menu in reverse video to indicate
that your application is busy processing the message.  When
you done with whatever action is indicated, you need to
return the title to a normal state. This is done with

\begin{verbatim}
    menu_tnormal(ad_menu, msg[3], TRUE);
\end{verbatim}

 (Remember that \verb"msg[3]" is the title's object number.)

    When your application is ready to terminate, it should
delete its menu bar.  Do this with the call:

\begin{verbatim}
    menu_bar(ad_menu, FALSE);
\end{verbatim}

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Getting fancy}

  The techniques above represent the bare
minimum to handle menus.  In most cases, however, you will
want your menus to be more "intelligent" in displaying the
user's options.  For instance, you can prevent many user
errors by disabling inappropriate choices, or you can save
space on drop-downs by showing only one line for a toggle and
altering its text or placing and removing a check mark when
the state is changed.  This section discusses these and other
advanced techniques.

    It is a truism of user interface design that the best way
to deal with an error is not to let it happen in the first
place.  It  many cases, you can apply this principle to GEM
menus by disabling  choices which should not be used.  If
your application uses a "selection  precedes action" type of
interface, the type of object selected may  give the
information needed to do this.   Alternately, the state of
the  underlying program may render certain menu choices
illegal.

    GEM provides a call to disable and re-enable menu
options. The call is:

\begin{verbatim}
    menu_ienable(ad_menu, ENTRY, FALSE);
\end{verbatim}

 to disable a selection.  The entry will be grayed out when
it is drawn, and will not invert under the mouse and will not
be selected by the user. Substituting TRUE for FALSE
re-enables the option.  \verb"ENTRY" is the name  of the object
which is being affected, as assigned in the RCS.

    Note that \verb"menu_ienable()" will not normally affect the
appearance or operation of menu TITLE entries.  However,
there is an undocumented feature which allows this.  If \verb"ENTRY"
is replaced by the object number of a title bar entry with
its top bit set, then the entire associated drop-down will be
disabled or re-enabled as requested, and the title's
appearance will be changed.  But, be warned that this feature
did not work reliably in some early versions of GEM.  Test it
on your copy of ST GEM, and use it with caution when you
cannot control the version under which your application may
run.

    It is also possible to disable menu entries by directly
altering the \verb"DISABLED" attribute within the \verb"OB_STATE" word.
The routines \verb"enab_obj()" and \verb"disab_obj()" in the listing show
how this is done.  They are also used in \verb"set_menu()", which
follows them immediately.

    \verb"Set_menu()" is a utility which is useful when you wish to
simultaneously enable or disable many entries in the menu
when the program's state changes or a new object is selected
by the user.   It is called with

\begin{verbatim}
    set_menu(ad_menu, vector);
\end{verbatim}

 where vector is a pointer to an array of WORDs.  The first
word of the array determines the default state of menu
entries.  If it is TRUE, then \verb"set_menu()" enables all entries
in every drop-down of the menu tree, except that the DESK
drop-down is unaffected.  If it is FALSE, then every menu
entry is disabled.

    The following entries in the array are the numbers of
menu entries which are to be toggled to the reverse of the
default state. This list is terminated by a zero entry.

    The advantage of \verb"set_menu()" is that it allows you to
build a collection of menu state arrays, and associate one
with each type of user-selected object, program state, and so
on.  Changing the status of the menu tree may then be
accomplished with a single call.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Check, please?}

One type of state indicator which may
appear  within a drop-down is a checkmark next to an entry.
You can add the  checkmark with the call:

\begin{verbatim}
    menu_icheck(ad_menu, ENTRY, TRUE);
\end{verbatim}

 and remove it by replacing the TRUE with FALSE.  As above,
\verb"ENTRY" is the name of the menu entry of interest.  The
checkmark appears inside the left boundary of the entry
object, so leave some space for it.

    The \verb"menu_icheck()" call is actually changing the state of
the \verb"CHECKED" flag within the entry object's \verb"OB_STATE" word.  If
necessary, you may alter the flag directly using \verb"do_obj()" and
\verb"undo_obj()" from the example listing.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Now you see it, now you don't}

You can also alter the
text  which appears in a particular menu entry (assuming that
the entry is  a \verb"G_STRING" object).  The call

\begin{verbatim}
    menu_text(ad_menu, ENTRY, ADDR(text));
\end{verbatim}

 will substitute the null-terminated string pointed to by
text for whatever is currently in \verb"ENTRY".  Remember to make
the drop-down wide enough to handle the largest text string
which you may substitute.  In the interests of speed,
\verb"G_STRINGs" drawn within drop-downs are not clipped, so you may
get garbage characters on the desktop if you do not size the
drop-down properly!

    The \verb"menu_text()" call actually alters the \verb"OB_SPEC" field of
the menu entry object to point to the string which you
specify.  Since the menu tree is a static data structure
which may be directly accessed by the AES at any time, be
sure that the string is also statically allocated and that it
is not modified without first being delinked from the menu
tree. Failure to do this may result in random crashes when
the user accesses the drop-down!

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Lunch and dinner menus}

Some applications may have such
a wide  range of operations that they need more than one menu
bar at different  times.  There is no problem with having
more than one menu tree in a  resource, but the AES can only
keep track of one at a time.  Therefore,  to switch menus you
need to use

\begin{verbatim}
    menu_bar(ad_menu1, FALSE);
\end{verbatim}

to release  the first menu, then use

\begin{verbatim}
    menu_bar(ad_menu2, TRUE);
\end{verbatim}

to load the second menu tree.

    Changing the entire menu is a drastic action.  Out of
consideration for your user, it should be associated with
some equally obvious change in the application which has just
been manually requested.  An example  might be changing from
spreadsheet to data graphing mode in a multi-function
program.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Do it yourself}

In one of the next sections, I will discuss how
to set up user-defined drawing objects.  If you have already
discovered them  on your own, you can use them within a
drop-down or as a title entry.

    If the user-defined object is within a drop-down, its
associated drawing code will be called once when the
drop-down is first drawn. It will then be called in
"state-change" mode when the entry is highlighted (inverted).
This allows you to use non-standard methods to show
selection, such as outlines.

    If you try to insert a user-defined object within the
menu title area, remember that the \verb"G_TITLE" object which you
are replacing includes part of the dark margin of the bar.
You will need to experiment with your object drawing code to
replicate this effect.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Make pretty}

  There are a number of menu formatting
conventions which have become standard practice.  Using these
gives your application a recognizable "look-and-feel" and
helps users learn it.  The following section reviews these
conventions, and supplies a few hints and tricks to obtain a
better appearance for you menus.

    The second drop-down is customarily used as the FILE
menu.  It  contains options related to loading and saving the
files used by the  application, as well as entries for
clearing the workspace and  terminating the program.

    You should avoid crowding the menu bar.  Leave a couple
of spaces between each entry, and try not to use more than
70\% of the bar.  Not only does this look better, but you will
have space for longer words if you translate your application
to a foreign language.

    Similarly, avoid cluttering menu drop-downs.  Try to keep
the number of options to no more than ten unless they are
clearly related, such as colors.  Separate off dissimilar
entries with the standard disabled dashes line.  (If you are
using \verb"set_menu()", remember to consider the separators when
setting up the state vectors.)

    If the number of options grows beyond this bound, it may
be time to move them to a dialog box.  If so, it is a
convention to put three dots following each menu entry which
leads to a dialog. Also, allow a margin on the menu entries.
Two leading blanks and a minimum of one trailing blank is
standard, and allows room for checkmarks if they are used.

    Dangerous menu options should be far away from common
used entries, and are best separated with dashed lines.  Such
options should either lead to a confirming go/no-go alert, or
should have associated "undo" options.

    After you have finished defining a menu drop-down with
the RCS,  be sure that its entries cover the entire box.
Then use ctrl-click to  select the drop-down itself, and SORT
the entries top to bottom.  This  way the drop-down draws in
smoothly top to bottom.

    Finally, it is possible to put entries other than
\verb"G_STRINGs" into drop-downs.  In the RCS, you will need to
import them via the clipboard from the Dialog mode.

    Some non-string object, such as icons and images, will
look odd  when they are inverted under the mouse.  There is a
standard trick for  dealing with this problem.  Insert the
icon or whatever in the drop-down first.  Then get a \verb"G_IBOX"
object and position and size it so that it covers the first
object as well as the extra area you would like to be
inverted.

    Edit the \verb"G_IBOX" to remove its border, and assign the
entry name  to it.  Since the menu manager uses \verb"objc_find()",
it will detect and invert this second object when the mouse
moves into the drop-down. 
Finally, {\bf do not} sort a drop-down which has been set  up this
way!


\newpage

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\section{An insider's AES tricks}

     This chapter of ST PRO  GEM is
devoted to exploring some of the little documented,  but powerful,
features  of GEM.   Like the authors of most complex systems,  the
GEM  programmers left behind a set of "hooks",  powerful  features
which would aid them in enhancing the system later.  I am going to
lay  out  a number of these methods which have served me  well  in
making  creative use of the AES.   You will find that most of them
concern  the object and form libraries,  since I was most involved
in those parts of GEM.  There are probably many more useful tricks
waiting  to be found in other parts of GEM,  so if you happen onto
one, please let me know in the Feedback! The listing for this
chapter is {\tt GEMCL11.C}.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Powerful objects}

    The  first  four tricks all involve  augmenting  standard  AES
objects.   This is a powerful technique for two  reasons.   First,
you  can  take  advantage  of the  regular  AES  object  and  form
libraries  to draw and handle most of your objects,  so that  your
program need only process the exceptions.  Second, you can use the
RCS  to  copy  the  special  objects  into  multiple  dialogs   or
resources.   These  four tricks are Extended Object  Types,  User-
defined Objects,  \verb"TOUCHEXIT",  and \verb"INDIRECT".  Let's look at each of
them in turn.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Extended object types}

    If you look at the AES Object Library documentation,  you will
notice that the values for the \verb"OB_TYPE" field in an object are  all
32 or less.   This means that a number of bits are unused in  this
field.   In fact,  the AES completely ignores the top byte of  the
\verb"OB_TYPE" field.   In addition, the RCS ignores the top byte, but it
also  preserves  its value when an object  is  read,  written,  or
copied.

     This  gives  you one byte per object to use as you  see  fit.
Since  the  processing of an object or dialog is (so far)  in  the
hands of the AES,  the best uses of Extended Types are in flagging
methods for initializing an object or handling its value when  the
dialog  completes.

     For  example,  you  might  have  several  dialogs  containing
editable numeric fields.   The Extended Type of each numeric field
could be set to the index of the corresponding value in an  array.
Then your application's dialog initialization code could scan  the
object  tree  for  such objects,  pick up  the  appropriate  value
from the array and convert it to ASCII,  storing the result in the
resource's  string  area.   When the dialog was finished,  another
pass could be made to reconvert the ASCII to binary and store away
the results in the array.   (Note that the \verb"map_tree()" utility from
a previous chapter will scan an entire resource tree.)

     Another  application  is  to assign  uniform  codes  to  exit
buttons  in  dialogs.   If you give every "OK" button an  Extended
Type  of one,  and every "Cancel" button an Extended Type of  two,
then  you  needn't  worry about naming every  exit  object.   Just
examine  the Extended Type of the object returned by \verb"form_do",  and
proceed accordingly.

     The catch, of course, is that you have to find a way to enter
the  Extended  Type code in the first place.   Version 1.0 of  the
RCS, as shipped with the Atari developer's kit, makes no provision
for this.  So you have your choice of two methods for creating the
first  object with each Extended Type code.

     First,  you can dump out a C source of a resource, insert the
new type code by hand,  and regenerate the resource with \verb"STCREATE".
Alternately,  you could carefully modify the binary resource using
SID.   You will probably want to reread the AES object manual and 
use the C source as a guide when doing so.
In both cases, you should make things easy on yourself by creating
a  one  dialog resource with only a single object other  than  the
root.   Version  2.0  of  the RCS will let you directly  enter  an
Extended Type, but it has not yet been released for the ST by DRI.

     Once  you have created a prototype extended object by  either
method, you can use the RCS to propogate it.  The safest way is to
use the MERGE option to add the modified tree to the resource  you
are building.  Then copy the prototype object via the clipboard to
your dialog(s), deleting the extra tree when you are done.  If you
are  using several different extended objects,  you can use  MERGE
and clipboard copies to get them all into one tree which will then
become your own object library.

     The  second way of using RCS is easier,  but more  dangerous.
If you want to try the following technique,  BACK UP YOUR RCS DISK
FIRST!   Put  simply,  the RCS does not care what is in its dialog
partbox. It will make copies of anything that it finds there! This
gives you the option of using the RCS on ITS OWN RESOURCE in order
to add your customized objects to the partbox.

     To do this, open RCS.RSC from the RCS.  Since there is no DEF
file,  you will get a collection of question mark icons.   Use the
NAME option to make TREE5 into a DIALOG.    Open it,  and you will
see the dialog partbox.

     Now you can use the MERGE technique described above to insert
your  customized  objects.   Then SAVE the modified resource,  and
rerun the RCS.  Your new objects should now appear in the partbox.
If  you added several,  you may have to stretch the partbox to see
them  all.   You can now make copies of the new objects just  like
any other part.  (Note: DO NOT modify the alert or menu partboxes,
you will probably crash the RCS.)

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{User-defined objects}

    The one type of object which was not discussed in the  earlier
chapters on  AES objects was \verb"G_USERDEF",  the  programmer  defined
object.   This  is  the  hook  for  creating  objects  with  other
appearances  beyond those provided by the standard  AES.   By  the
way, you should note that the \verb"G_PROGDEF" and \verb"APPLBLK" mnemonics used
in  the  AES documents are incorrect;  the actual  names  as  used
defined \verb"OBDEFS.H" are \verb"G_USERDEF" and \verb"USERBLK".

     The  RCS does not support the creation of \verb"G_USERDEF"  objects,
since  it  has  no idea how they will be drawn  by  your  program.
Instead,  you  must insert a dummy object into your resource where
you  want  the  \verb"G_USERDEF"  to appear,  and  patch  it  after  your
application performs its resource load.

     You   must  replace  the  object's  existing \verb"OB_TYPE" with
\verb"G_USERDEF",  though you may still use the upper byte as an Extended
Type.   You  must  also  change the \verb"OB_SPEC" field to be  a  32-bit
pointer  to  a \verb"USERBLK" structure.   An \verb"USERBLK" is simply two  LONG
(32-bit)  fields.   The  first is the address of the drawing  code
associated  with  the  user  defined object.   The  second  is  an
arbitrary 32-bit value assigned to the object by your application.

This one is useful if several objects have different \verb"USERBLK"s but
call the same drawing code, because the code can detect who called it
without without evaluating \verb"pb_tree" or \verb"pb_obj". When called,
AES will pass the PARMBLK structure which also contains position and size of
the object. Whenever the object needs to be redrawn the \verb"objc_draw"
or \verb"objc_change" calls in turn call \verb"ub_code" as a subroutine
of the AES. So the routine will be called in supervisor mode and all
registers except for \verb"A0-A2/D0-D2" MUST be saved. Also \verb"ub_code"
may NOT make any AES calls because GEM is not reentrant. VDI, XBIOS, BIOS
and GEMDOS routines may be called however. \verb"ub_code" will only be called
if the object lies within the clipping area. If \verb"ub_code" was called 
during an \verb"objc_change" call, the state of the object may just have
changed. Then, parameters \verb"pb_prevstate" and \verb"pb_currstate"
in the structure \verb"PARMBLK" contain different values.

The object's status bits will be evaluated immediately after return
of \verb"ub_code". These are not taken from the \verb"OBJECT" structure,
but are returned by \verb"ub_code"! So it's sufficient to return
\verb"pb_currstate" to make AES change the object properly.

     You can designate objects for conversion to \verb"G_USERDEFs" in the
normal fashion by assigning them names which are referenced one by
one in your initialization code.   You can also combine two tricks
by using the Extended Type field as a designator for objects to be
converted to \verb"G_USERDEF".  Each tree can then be scanned for objects
to  be converted.   There is a short code segment in the  listings
which demonstrates this technique.

     My  usual  convention  is to define new  drawing  objects  as
variants  of  existing objects,  using the Extended Type field  to
designate the particular variation.   Thus an Extended Type of one
might designate a \verb"G_BUTTON" with rounded corners,  while a value of
two  could  flag  a \verb"G_STRING" of boldface text.   When  using  this
technique,  the  RCS can be used to build a rough facsimile of the
dialog  by inserting the basic object type as  placeholders.   The
existing  \verb"OB_SPEC"  information can then be copied  to  the  second
position in the \verb"USERBLK" when the object is initialized.

     One final note before moving on:  There is no reason that the
\verb"USERBLK"  cannot be extended beyond two fields.   You might want to
add  extra words to store more information related to drawing  the
object, such as its original type.

     The  AES will call your drawing code whenever  the \verb"G_USERDEF"
needs  to be drawn.   This occurs when you make an \verb"objc_draw"  call
for its tree,  or when an \verb"objc_change" occurs for that object.   If
your user-defined object is in a menu drop-drop, then your drawing
code will be called any time the user exposes that menu.

     Before  getting  into the details of the AES  to  application
calling  sequence,  some  warnings are in order.   First,  remember
that your drawing code will execute in the AES' context, using its
stack.   Therefore,  be careful not to overuse the stack with deep
recursion, long parameter lists, or large dynamic arrays.  Second,
the  AES  is NOT re-entrant,  so you may not make ANY calls to  it
from within a \verb"G_USERDEF" procedure.   You may,  of course, call the
VDI.   Finally,  realize  that drawing code associated with a menu
object may be called by the AES at any time.   Exercise great care
in  sharing  data  space between such code and  the  rest  of  the
application!

     When your drawing code is called by the AES, the stack is set
up  as if a normal procedure call had occured.   There will be one
parameter  on the stack:  a 32-bit pointer to a \verb"PARMBLK" structure.
This structure lies in the AES' data space, so do not write beyond
its end!

     The  \verb"PARMBLK" contains 15 words.   The first two are the  long
address of the object tree being drawn,  and the third word is the
number of the \verb"G_USERDEF" object.   You may need these values if the
same  drawing  code is used for more than one object  at  a  time.
Words  four  and five contain the previous  and  current \verb"OB_STATE"
values of the object.  If these values are different, your drawing
code  is  being  called in response  to  an  \verb"objc_change"  request.
Otherwise, the active AES call is an \verb"objc_draw".

     Words six through nine contain the object's rectangle on  the
screen.   Remember  that  you cannot call \verb"objc_offset"  within  the
drawing code,  so you will need these values!  The next four words
contain the clipping rectangle specified in the active \verb"objc_change"
or \verb"objc_draw" call.   You should set the VDI clip rectangle to this
value before doing any output to the screen.

     The last two words in the \verb"PARMBLK" contain a copy of the extra
32-bit parameter from the object's \verb"USERBLK".   If you have followed
the  method of copying an \verb"OB_SPEC" into this location,  these words
will be your pointer to a string, or \verb"BITBLK", or whatever.

     When  your drawing routine is done,  it should return a  zero
value  to  the AES.   This is a "magic" value;  anything else will
stop the drawing operation.

     The listing contains a sample drawing routine which  defines
one extended drawing object,  a rounded rectangle button.  You can
use  this procedure as a starting point for your own User  Defined
objects.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Put anything you want on the Desktop!}

     In a previous chapter I described the use  of  the  \verb"WF_NEWDESK"
\verb"wind_set"  call to substitute your own object tree for  the  normal
green  desktop background.   If the tree you supply contains  User
Defined  objects,  you can draw whatever you want on the  desktop!
Some  of the things you might try are free hand drawings  imported
in  metafile  format from EasyDraw,  or whole  screen  bit  images
generated by Degas.   If you do the latter, you will have to store
the entire image off screen and blit parts of it to the display as
requested.

     In  any case,  remember that your desktop drawing code can be
called any time that a window is moved,  so exercise the same care
as with a menu drawer.   Also, be aware that making the \verb"WF_NEWDESK"
call  does  not force an immediate redraw of the desktop.   To  do
that, do a \verb"form_dial(3)" call for the entire desktop rectangle.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{The Touchexit Flag}

   The  \verb"TOUCHEXIT" attribute is an alternative to  the  more  usual
\verb"EXIT".   When the \verb"TOUCHEXIT" bit is set in an object's \verb"OB_FLAG" word,
the \verb"form_do" routine will exit immediately when the mouse button is
pressed  with  the  cursor  over  the  object.    Your  code   can
immediately take control of the mouse and display, without waiting
for the release of the button.  This method is used for generating
effects such as slider bars within otherwise normal dialogs.

     The  easiest  way to code a \verb"TOUCHEXIT" handler is to  place  a
loop  around the \verb"form_do" call.   If the object number returned  is
\verb"TOUCHEXIT",  then the animation procedure is called,  followed by a
resumption   of  the  \verb"form_do"  (WITHOUT  recalling  \verb"form_dial"   or
\verb"objc_draw"!).   If the object returned is a normal \verb"EXIT", the dialog
is  complete and control flows to the cleanup code.

     There is one idiosyncrasy of \verb"TOUCHEXIT" which should be noted.
When the AES "notices" that the mouse button has been pressed over
a \verb"TOUCHEXIT",  it immediately retests the button state.   If it has
already  been  released,  it  waits to see if  a  double click  is
performed.  If so, the object number returned by \verb"form_do" will have
its  high  bit set.   If you don't care about double clicks,  your
code should mask off this flag.   However, you may want to use the
double click to denote some enhanced action.  For example, the GEM
file selector uses a double click on one of the file name  objects
to indicate a selection plus immediate exit.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{The Indirect Flag}

    If the \verb"INDIRECT" bit is set in an object's \verb"OB_STATE"  word,  the
AES interprets the 32-bit \verb"OB_SPEC" field as a pointer to the memory
location  in which the {\em actual}\/ \verb"OB_SPEC" is to be found.   Like  User
Defined objects,  this capability is not supported by the RCS,  so
you  have to set up the \verb"INDIRECT" bit and alter the \verb"OB_SPEC" at  run
time.

     The value of \verb"INDIRECT" is that you can use it to associate  an
AES  object with other data or code.   The general technique is to
set  up  a table with a spare 32-bit location  at  its  beginning.
Then,  when initializing the application's resource,  you move the
true  \verb"OB_SPEC"  into  this location,  set the  \verb"INDIRECT"  flag,  and
replace the \verb"OB_SPEC" field with a pointer to the table.  The object
behaves normally during drawing and form handling. However, if you
receive  its  number  from  \verb"form_do"  or  \verb"objc_find",  you  have  an
immediate  pointer to the associated table,  without having to  go
through a lookup procedure.

     This  technique works well in programs like the GEM  Desktop.
Each  \verb"G_ICON" object is set up with \verb"INDIRECT".   Its \verb"OB_SPEC" goes to
the  beginning of a data area defining the associated  file.   The
blank  location at the beginning of file table is filled  up  with
the former \verb"OB_SPEC", which points to a \verb"ICONBLK".

     You  can also combine \verb"INDIRECT" with \verb"TOUCHEXIT"  when  creating
objects  that  must change when they are clicked by a  user.   For
instance,  a  color  selection  box  might be linked  to  a  table
containing  the various \verb"OB_SPEC" values through which  the  program
will cycle.   Each time the user clicked on the box, the \verb"TOUCHEXIT"
routine would advance the table pointer,  copy the next value into
the  dummy \verb"OB_SPEC" location at the front of the table,  and redraw
the object in its new appearance.

     A  programmer  who wanted to follow a  truly  object-oriented
"Smalltalkish" approach could use the \verb"INDIRECT" method to bind  AES
drawing  object to tables of associated procedures  or  "methods".
For instance, one procedure could be flagged for use when the user
clicked  on the object,  one when the object was dragged,  one for
double-click,  and  so on.   If the table structure was capable of
indicating  that  the true method was stored in another  table,  a
rudimentary form of class inheritance could be obtained.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Instant co-routines}

     We turn to the AES event and message system for  this  trick.
While   some  languages  like  Modula  2  provide  a  method   for
implementing  co-routines,  there  is  no such  capability  in  C.
However,  we  can  effectively  fake it by  using  the  AES  event
library.

     As  already  seen in an earlier column,  an  application  can
write a message to its own event queue using the \verb"appl_write"  call.
Usually, this is a redraw message, but there is nothing to prevent
you from using this facility to send messages from one routine  in
your program to another.  To set up co-routines using this method,
they  would  be  coded  as separate  procedures  called  from  the
application's main event loop.

     When  one  of the co-routines wanted to call  the  other,  it
would  post  a message containing the request and  any  associated
parameters into the application's queue and then return.  The main
loop  would find the message and make the appropriate call to  the
second co-routine.  It it was necessary to then re-enter the first
co-routine  at  the  calling point,  the  original  message  could
contain an imbedded reply message to be sent back when the request
was  complete.   A  simple switch structure could then be used  to
resume at the appropriate point.

     There  are two potential problems in using this method.   The
first is the limited capacity of the application event queue.  The
queue  contains  eight entries.    While the AES  economizes  this
space  by  merging redraws and multiple events,  it  cannot  merge
messages.   Because  of this limit,  you must be extremely careful
when  one  message received has the potential to generate  two  or
more  messages sent.   Unless this situation is carefully managed,
you  can get a sort of "cancer" which will overflow the queue  and
probably crash your application.

     The second danger involves race conditions.   Message sent by
the  application  are posted to the end of the  queue.   If  other
events  have occurred,  such as mouse clicks or keyboard  presses,
they will be seen and processed ahead of the application generated
message.   This  implies  that you cannot use this method  if  the
program must complete its action before a new user generated event
can be processed.

\subsection{Deadlocks}

     One note on deadlocks: you may have noticed, that sometimes AES
doesn't react to user input until the mouse button is clicked several
times. This happens because the GEM is not a true multitasking system.
The mouse interrupt writes the events into a circular buffer. This
buffer can store 32 events. If AES is not called for a while, the
buffer may overflow, resulting in the loss of events. If the event is
releasing a mouse button, and it is lost, the program is still waiting
for the button to be released. And the user is confused, because the
system "hangs".

     Some sources recommend an \verb"evnt\_timer(0L)" that gives AES
the chance to empty its event buffer. GEM 2.x provides a call \verb"appl\_yield"
that has the same result, but needs less time. Fortunately this function
is also available in Atari's GEM 1.x. In addition to the "magic" values
\verb"0x73" and \verb"0xC8" for VDI and AES respectively, it's possible
to assign the value \verb"\0xC9" to Register \verb"D0" before calling the
GEM trap. That will cause the system to jump directly to the AES internal
\verb"appl\_yield" routine. Using \verb"appl\_yield" instead of \verb"evnt\_timer"
will save considerable amounts of time: 1000 calls to \verb"appl\_yield"
take 1.4 seconds compared to 20 seconds for 1000 calls to \verb"evnt\_timer"!
Here is an assembly language routine that calls \verb"appl\_yield":

\begin{verbatim}
appl_yield:
        move.w #$C9,d0
        trap   #2
        rts
\end{verbatim}

    This routine can be added to the GEM-library. It takes no parameter
and it doesn't return anything. It just keeps the event dispatcher happy.

\newpage

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\section{VDI Graphics: Lines and Solids}

     This chapter of ST PRO GEM will explore the fundamentals of
VDI graphics  output. We will take a look at the commands necessary to
output simple graphics such as lines,  squares and circles as well
as  more complex figures such as polygons.   We will then
 take a first look at graphics text output,  with an emphasis
on  ways  to  optimize its drawing speed. As usual,  there is  a
demonstration program with  this chapter under the name {\tt GEMCL09.C}.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{A bit of history}

    One  of  the reasons that the VDI can  be  confusing  is  that
drawing anything at all,  even a simple line,  can involve setting
around four different VDI parameters before making the draw  call!
(Given  the state of the GEM documents,  just FINDING them can  be
fun!)  Looking backwards a bit sheds some light on why the VDI  is
structured this way,  and also gives us a framework for organizing
a discussion of graphics output.

     The GEM VDI closely follows the so-called GKS standard, which
defines  capabilities  and calling sequences  for  a  standardized
graphic  input/output system.   GKS is itself an evolution from an
early system called "Core".   Both of these standards were born in
the  days  when  pen plotters,  vectored  graphics  displays,  and
minicomputers  were  the  latest items.   So,  if you  wonder  why
setting  the drawing pen color is a separate command,  just  think
back  a  few  years when it actually meant  what  it  says!   (The
cynical   may   choose   instead  to  ponder   the   benefits   of
standardization.)

     When  doing  VDI  output,  it helps if you pretend  that  the
display screen really is a plotter or some other separate  device,
which  has  its own internal parameters which you can set  up  and
read  back.   The class of VDI commands called Attribute Functions
let  you set the parameters.   Output Functions cause the "device"
to  actually  draw  someone once it is  configured.   The  Inquire
Functions let you read back the parameters if necessary.

     There  are two parameters which are relevant no  matter  what
type of object you are trying to draw.   They are the writing mode
and  the clipping rectangle.   The writing mode is similar to that
discussed in the column on raster operations.   It determines what
effect the figure you are drawing will have on data already on the
screen.  The writing mode is set with the call:

\begin{verbatim}
          vswr_mode(vdi_handle, mode);
\end{verbatim}

   ({\tt vdi\_handle},  here  and  below,  is the  handle  obtained  from
\verb"graf_handle" at the beginning of the program.  Mode is a word which
may be one of:

\begin{description}
\item[1] Replace Mode
\item[2] Transparent Mode
\item[3] XOR mode
\item[4] Reverse Transparent Mode
\end{description}

     In  replace mode,  whatever is on the screen is  overwritten.
If  you are writing characters,  this means the background of each
character cell will be erased.

     In  transparent  mode,  only  the pixels directly  under  the
"positive"  part  of the image,  that is,  where 1-bits are  being
written, will be changed.  When writing characters, the background
of the cell will be left intact.

     In XOR mode,  an exclusive or is performed between the screen
contents and what is being written.   The effect is to reverse the
image under areas where a 1-bit occurs.

     Reverse transparent is like transparent,  but with a "reverse
color  scheme".   That  is,  only  places where a 0-bit is  to  be
put   are  changed  to  the  current  writing  color.    When  you
write  characters in reverse transparent (over white),  the effect
is reverse video.

     The  other  common parameter is the clipping  rectangle.   It
defines the area on the screen where the VDI is permitted to draw.
Any output which would fall outside of this area is ignored; it is
effectively a null operation.   The clip rectangle is set with the
call:

\begin{verbatim}
          vs_clip(vdi_handle, flag, pxy);
\end{verbatim}

   {\tt pxy} is a four-word array. \verb"Pxy[0]" and \verb"pxy[1]" are the X and Y
screen coordinates,  respectively,  of one corner of your clipping
rectangle.    \verb"Pxy[2]"  and  \verb"pxy[3]"  are  the  coordinates  of   the
diagonally opposite corner of the rectangle.   (When working  with
the  AES,  use  of  a  \verb"GRECT" to define  the  clip  is  often  more
convenient.  The routine \verb"set_clip()" in the listing does this.)

     {\tt flag} is set to TRUE if clipping is to be used.  If you set it
to  FALSE,  the  entire  screen is assumed to be fair  game.

     Normally,  you should walk the rectangle list for the current
window to obtain your clipping rectangles. 
However, turning off the clip speeds up all output
operations,  particularly text.  You may do this ONLY when you are
absolutely certain that the figure you are drawing will not extend
out of the top-most window, or out of a dialog.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{The line forms on the left}

     The  VDI  line  drawing  operations  include  polyline,  arc,
elliptical  arc,  and rounded rectangle.   I'll first look at  the
Attribute Functions for line drawing,  then go through the drawing
primitives themselves.

     The  most  common used line attributes are color  and  width.
The color is set with:

\begin{verbatim}
          vsl_color(vdi_handle, color);
\end{verbatim}

   where color is one of the standard VDI color  indices,  ranging
from  zero to 15.   (The  color  which
actually appears will depend on the pallette setting of your ST.)

     The  line width may only be set to ODD positive  values,  for
reasons  of  symmetry.   If you try to set an even value,  the VDI
will take the next lower odd value.  The call is:

\begin{verbatim}
          vsl_width(vdi_handle, width);
\end{verbatim}

     The  two  less  used line parameters are the  end  style  and
pattern.   With  the  end style you can cause the output  line  to
have rounded ends or arrowhead ends.  The call is:

\begin{verbatim}
          vsl_ends(vdi_handle, begin_style, end_style);
\end{verbatim}

   {\tt Begin\_style} and {\tt end\_style} are each words which  may  have  the
values zero for square ends (the default),  one for arrowed  ends,
or  two  for  rounded ends.   They determine the  styles  for  the
starting and finishing ends of the line, respectively.

     The line pattern attribute can select dotted or dashed  lines
as  well  as more complicated patterns.   Before  continuing,  you
should  note one warning:  VDI line output DOES NOT compensate for
pixel aspect ratio.  That is, the dashes on a line will look twice
as long drawn vertically on a medium-res ST screen as they do when
drawn horizontally.  The command for setting the pattern is:

\begin{verbatim}
          vsl_type(vdi_handle, style);
\end{verbatim}

   Style  is  a word with a value between 1  and  7.   The  styles
selected are:

\begin{description}
\item[1] Solid (the default)
\item[2] Long Dash
\item[3] Dot
\item[4] Dash, Dot
\item[5] Dash
\item[6] Dash, Dot, Dot
\item[7] (User defined style)
\end{description}

   The  user  defined  style is determined  by  a  16-bit  pattern
supplied  by the application.   A one bit in the pattern  turns  a
pixel on, a zero bit leaves it off.  The pattern is cycled through
repeatedly,  using the high bit first.  To use a custom style, you
must make the call:

\begin{verbatim}
          vsl_udsty(vdi_handle, pattern);
\end{verbatim}

  before doing \verb"vsl_type()".

     As  I  mentioned  above,   the  line  type  Output  Functions
available are polyline,  circular and ellliptical arc, and rounded
rectangle.   Each  has  its own calling sequence.   The call for a
polyline is:

\begin{verbatim}
          v_pline(vdi_handle, points, pxy);
\end{verbatim}

  {\tt points} tells how many vertices will appear on the polyline.  For
instance,  a  straight  line has two vertices:  the  end  and  the
beginning.   A closed square would have five,  with the first  and
last  identical.    (There  is  no  requirement  that  the  figure
described be closed.)

     The {\tt pxy} array contains the X and Y raster coordinates for the
vertices,  with a total of 2 * points entries.   \verb"Pxy[0]" and \verb"pxy[1]"
are the first X-Y pair, and so on.

     If you happen to be using the XOR drawing mode, remember that
drawing  twice  at  a point is equivalent to no  drawing  at  all.
Therefore,  for  a figure to appear closed in XOR mode,  the final
stroke  should actually stop one pixel short of the origin of  the
figure.

     You  may  notice  that  in the GEM  VDI  manual  the  rounded
rectangle  and arc commands are referred to as  GDPs  (Generalized
Drawing Primitives).  This denotation is historical in nature, and
has  no effect unless you are writing your own VDI bindings.

     The  rounded rectangle is nice to use for customized  buttons
in  windows and dialogs.   It gives a "softer" look to the  screen
than the standard square objects.  The drawing command is:

\begin{verbatim}
          v_rbox(vdi_handle, pxy);
\end{verbatim}

   {\tt pxy} is a four word array giving opposite corners of the
rectangle,  just as for the \verb"vs_clip()" call.   The corner  rounding
occurs  within  the  confines of  this  rectangle.   Nothing  will
protrude  unless  you specify a line thickness greater  than  one.
The  corner rounding is approximately circular;  there is no  user
control over the degree or shape of rounding.

     Both the arc and elliptical arc commands use a curious method
of  specifying  angles.   The units are tenths of degrees,  so  an
entire  circle is 3600 units.   The count starts at ninety degrees
right of vertical, and proceeds counterclockwise.  This means that
"3 o'clock" is 0 units,  "noon" is 900 units,  "9 o'clock" is 1800
units, and 2700 units is at "half-past".  3600 units take you back
to "3 o'clock".

     The command for drawing a circular arc is:

\begin{verbatim}
          v_arc(vdi_handle, x, y, radius, begin, end);
\end{verbatim}

   {\tt x}  and {\tt y} specify the raster coordinates of the  center  of  the
circle.   {\tt radius} specifies the distance from center to all  points
on the arc.   {\tt begin} and {\tt end} are angles given in units as described
above,  both with values between 0 and 3600.   The drawing of  the
arc  ALWAYS  proceeds  counterclockwise,   in  the  direction   of
increasing arc number.   So values of 0 and 900 for begin and  end
would  draw  a  quarter circle from  "three  o'clock"  to  "noon".
Reversing  the values would draw the other three quarters  of  the
circle.

     A  \verb"v_arc()"  command  which specifies a  "full  turn"  is  the
fastest  way to draw a complete circle on the screen.   Be warned,
however,  that  the circle drawing algorithm used in the VDI seems
to  have  some  serious  shortcomings at  small  radii!   You  can
experiment  with  the  CIRCLE primitive in  ST  Logo,  which  uses
\verb"v_arc()", to see what I mean.

     Notice  that if you want an arc to strike one or more  given
points on the screen,  then you are in for some trigonometry.   If
your  math  is  a  bit  rusty,  I highly  recommend  the  book  "A
Programmer's  Geometry",  by  Bowyer  and Woodwark,  published  by
Butterworths (London, Boston, Toronto).

     Finally, the elliptical arc is generated with:

\begin{verbatim}
          v_ellarc(vdi_handle, x, y, xrad, yrad, begin, end);
\end{verbatim}

 {\tt y}, {\tt y},  {\tt begin}, and {\tt end} are just as before.  
{\tt xrad}\/ and {\tt yrad} give the
horizontal and vertical radii of the defining ellipse.  This means
that  the distance of the arc from center will be {\tt yrad} pixels  at
"noon"  and  "half-past",  and it will be {\tt xrad} pixels at "3 and  9
o'clock".  Again, the arc is always drawn counterclockwise.

     There  are  a  number  of approaches  to  keeping  the  VDI's
attributes "in sync" with the actual output operations.   Probably
the  LEAST efficient is to use the Inquire Functions to  determine
the  current  attributes.   For  this  reason,  I have  omitted  a
discussion of these calls from this chapter.

     Another  idea  is  to keep a local copy  of  all  significant
attributes, use a test-before-set method to minimize the number of
Attribute  Functions which need to be called.   This puts a burden
on  the programmer to be sure that the local  attribute  variables
are correctly maintained.   Failure to do so may result in obscure
drawing  bugs.   If  your  application employs  user  defined  AES
objects, you must be very careful because GEM might call your draw
code  in the middle of a VDI operation (particularly if  the  user
defined objects are in the menu).

     Always  setting  the attributes is a simplistic  method,  but
often   proves  most  effective.    The  routines  \verb"pl_perim()"  and
\verb"rr_perim()"  in the listing exhibit this  approach.   Modification
for  other  primitives  is straightforward.   This style  is  most
useful  when  drawing  operations  are  scattered  throughout  the
program,  so that keeping track of the current attribute status is
difficult.  Although inherently inefficient, the difference is not
very  noticable if the drawing operation requested is itself  time
consuming.

     In  many  applications,  such  as data graphing  programs  or
"Draw"  packages,  the output operations are centralized,  forming
the primary functionality of the code.   In this case,  it is both
easy  and  efficient  to keep track of  attribute  status  between
successive drawing operations.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Solids}

    There  are  a wider variety of VDI  calls  for  drawing  solid
figures.   They  include rectangle or  bar,  disk,  pie,  ellipse,
elliptical  pie,  filled rounded rectangle,  and filled  polygonal
area.   Of course,  filled figure calls also have their own set of
attributes which you will need to set.

     The  fill color index determines what pen color will be  used
to draw the solid.  It is set with:

\begin{verbatim}
          vsf_color(vdi_handle, color);
\end{verbatim}

     {\tt color} is just the same as for line drawing.   A solid may  or
may not have a visible border.  This is determined with the call:

\begin{verbatim}
          vsf_perimeter(vdi_handle, vis);
\end{verbatim}

   {\tt vis} is a Boolean.   If it is true,  the figure will be given  a
solid one pixel outline in the current fill color index.   This is
often  useful  to improve the appearance of solids  drawn  with  a
dithered fill pattern.  If {\tt vis}\/ is false, then no outline is drawn.

     There are two parameters which together determine the pattern
used  to  fill your figure.   They are called interior  style  and
interior  index.   The style determines the general type of  fill,
and the index is used to select a particular pattern if necessary.
The style is set with the command:

\begin{verbatim}
          vsf_interior(vdi_handle, style);
\end{verbatim}

  where {\tt style}\/ is a value from zero through four.   Zero selects  a
hollow  style:  the  fill is performed in  color  zero,  which  is
usually  white.   Style one selects a solid fill with the  current
fill  color.   A style of two is called "pattern" and a  three  is
called "hatch", which are terms somewhat suggestive of the options
which can then be selected using the interior index.   Style  four
selects the user defined pattern, which is described below.

     The  interior  index is only significant for styles  two  and
three. To set it, use:

\begin{verbatim}
          vsf_style(vdi_handle, index);
\end{verbatim}

   (Be careful here: it is very easy to confuse this call with the
one  above  due  to the unfortunate choice of  name.)   The {\tt  index}\/ 
selects the actual drawing pattern.  The GEM VDI manual shows fill
patterns corresponding to index values from 1 to 24 under style 2,
and  from  1 to 12 under style 3.   However,  some  of  these  are
implemented  differently on the ST.   Rather than try to  describe
them all here, I would suggest that you experiment.  You can do so
easily  in  ST Logo by opening the Graphics  Settings  dialog  and
playing with the style and index values there.

     The user defined style gives you some interesting options for
multi-color fills.  It is set with:

\begin{verbatim}
          vsf_udpat(vdi_handle, pattern, planes);
\end{verbatim}

    {\tt planes}  determines the number of color planes in  the  pattern
which  you  supply.   It  is  set to one  if  you  are  setting  a
monochrome  pattern.   (Remember,  monochrome is  not  necessarily
black).   It may be set to higher values on color systems: two for
ST medium-res mode, or four for low-res mode.  If you use a number
lower than four under low-res, the other planes are zero filled.

     The {\tt pattern} parameter  is  an array of  words  which  is  a
multiple  of  16 words long.  The pattern determined is 16  by  16
pixels,  with each word forming one row of the pattern.   The rows
are  arranged top to bottom,  with the most significant bit to the
left.   If  you  have selected a multi-plane pattern,  the  entire
first plane is stored, then the second, and so on.

       Note that to use a multi-plane pattern, you set the writing
mode  to replace using \verb"vswr_mode()".   Since the each plane can  be
different,  you can produce multi-colored patterns.   If you use a
writing   color  other  than  black,   some  of  the  planes   may
"disappear".

     Most  of  the  solids Output Functions  have  analogous  line
drawing commands.   The polyline command corresponds to the filled
area primitive.  The filled area routine is:

\begin{verbatim}
          v_fillarea(vdi_handle, count, pxy);
\end{verbatim}

    {\tt count}  and {\tt pxy} are just the same as  for  \verb"v_pline()".   If  the
polygon  defined  by \verb"pxy" is not closed,  then the VDI  will  force
closure  with  a straight line from the last to the  first  point.
The  polygon may  be concave or self-intersecting.   If  perimeter
show is on, the area will be outlined.

     One  note of caution is necessary for both  \verb"v_fillarea()"  and
\verb"v_pline()".   There is a limit on the number of points which may be
stored in \verb"pxy[]".   This limit occurs because the contents of \verb"pxy[]"
are copied to the \verb"intin[]" binding array before the VDI is  called.
You  can  determine  the maximum number of  vertices  by  checking
\verb"intout[14]" after using the extended inquire function \verb"vq_extnd()".

     For  reasons unknown to this writer,  there are TWO different
filled rectangle commands in the VDI.  The first is

\begin{verbatim}
          vr_recfl(vdi_handle, pxy);
\end{verbatim}

    {\tt Pxy} is a four word array defining two opposite corners of  the
rectangle,  just  as  in  \verb"vs_clip()".   \verb"Vr_recfl()"  uses  the  fill
attribute settings, except that it NEVER draws a perimeter.

     The other rectangle routine is \verb"v_bar()", with exactly the same
arguments  as  \verb"vr_recfl()".    The  only  difference  is  that  the
perimeter  setting  IS  respected.   These two  routines  are  the
fastest way to produce a solid rectangle using the VDI.   They may
be  used in XOR mode with a BLACK fill color to quickly invert  an
area  of  the screen.   You can improve the speed even further  by
turning off the clip (if possible), and byte aligning the left and
right edges of the rectangle.

     Separate commands are provided for solid circle and  ellipse.
The circle call is:

\begin{verbatim}
          v_circle(vdi_handle, x, y, radius);
\end{verbatim}

   and the ellipse command is:

\begin{verbatim}
          v_ellipse(vdi_handle, x, y, xrad, yrad);
\end{verbatim}

    All of the parameters are identical to those given  above  for
\verb"v_arc()"  and \verb"v_ellarc()".   The solid analogue of an arc is a  "pie
slice".  The VDI pie commands are:

\begin{verbatim}
          v_pieslice(vdi_handle, x, y, radius, begin, end);
\end{verbatim}

  for a slice from a circular pie, and

\begin{verbatim}
          v_ellpie(vdi_handle, x, y, xrad, yrad, begin, end);
\end{verbatim}

   for a slice from a "squashed" pie.   Again,  the parameters are
identical  to  those in \verb"v_arc()" and  \verb"v_ellarc()".   The  units  and
drawing  order  of angles are also the  same.   The  final  solids
Output Function is:

\begin{verbatim}
          v_rfbox(vdi_handle, pxy);
\end{verbatim}

  which draws a filled rounded rectangle.   The {\tt pxy}\/ array  defines
two  two  opposite  corners of the  bounding  box,  as  shown  for
\verb"vs_clip()".

     The  issues involved in correctly setting the VDI  attributes
for a fill operation are identical to those in drawing lines.  For
those  who  want to employ the "always set" method,  I have  again
included  two  skeleton  routines in the listing,  which  can  be
modified as desired.
% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

\newpage
\section{VDI Graphics: Text Output}

We will now look at simple VDI  text output,  and ways to optimize
its  speed. To  keep  the size of this first discussion  of  text  within
reason, I am going to restrict it to use of the mono-spaced system
font   in  its  default  size  and  orientation.    Discussion  of
alternate and proportionally spaced fonts,  baseline rotation, and
character scaling will be a later chapter. Sample code is provided
in {\tt GEMCL10.C}.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Definitions}

This chapter  makes use of  some  terminology
which may be unfamiliar if you have not used digital typefaces.  A
mono-spaced  font  is  one in which  each  character  occupies  an
identically  wide  space on the screen.   A proportional font  has
characters  which occupy different widths.   For instance,  an 'l'
would probably be narrower than a 'w'.

    Text may be "justified" right,  left,  or center.  This means
that  the right character,  left character,  or center position of
the  text  string is constrained to a given location.   In  common
usage,  a  page  of text is "ragged right" if its lines  are  left
justified only.   The text page is "fully justified",  "justified"
or  (ambiguously)  "right justified" if BOTH the  left  and  right
characters are contrained to fixed columns.  Full justification is
produced  by  inserting extra blank characters in the  case  of  a
mono-spaced font,  or by adding extra pixel columns in the case of
proportional output.

     A  text character (in a monospaced font) is written inside  a
standard sized cell or box.  Vertically, the cell extends from the
"top  line" down to the "bottom line".   If there are one or  more
blank  lines at the top or bottom,  they are called "leading"  and
are  used  to separate lines of text.   The characters  themselves
always  fall between the "ascent line",  which is the highest line
reached by characters such as 'd' and 'l', and the "descent line",
which  is the lowest line in characters like 'q' and  'g'.   Other
locations  of  interest are the "half line",  which is the top  of
characters  like  'a' or 'n',  and the "base line",  which is  the
bottom of characters which do not have descenders.

     Before  plunging into the Attribute Functions for  text,  you
should  note  that  the  writing  mode  (\verb"vswr_mode")  and  clipping
rectangle  (\verb"vs_clip") attributes discussed earlier
also  pertain  to  text.   Since much of the  discussion  of  text
optimization  will  center on these attributes,  you may  want  to
review them.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Text attributes}

The writing color for graphics text is set
with the command:

\begin{verbatim}
          vst_color(vdi_handle, color);
\end{verbatim}

{\tt color} is a word value between 0 and 15 which
designates  the  output  color index.   As discussed  in  previous
columns,  the  actual  color  which appears is  dependent  on  the
current  palette  settings.   In  applications such  as  word  and
outline  processors  it  is important that  characters  and  their
background  provide  good contrast to avoid eyestrain.   In  these
situations,  you  may  want to use the \verb"setPalette" and/or  \verb"setColor"
XBIOS  functions  to  force the palette to a  known  state  before
starting the application.

     You  can choose a variety of special output effects for  your
text with the call:

\begin{verbatim}
          vst_effects(vdi_handle, effects);
\end{verbatim}

{\tt effects} is a single flag word,  with the bits having the following
significance:

\begin{description}
\item[0] Thicken
\item[1] Lighten
\item[2] Skew
\item[3] Underline
\item[4] Outline
\item[5] Shadow
\end{description}

In each case,  turning the bit on selects the effect.   Otherwise,
the  effect  is  off.   Any  number of  multiple  effects  may  be
selected, but the result may not always be pleasing or legible.

     The  "thicken"  effect widens the character  strokes  by  one
pixel,   resulting  in  the  appearance  of  boldface  type.   The
"lighten" effect superimposes a half-tone dither on the character.
This mode is useful for indicating non-selectable text items,  but
is not legible enough for other purposes.

     The  skew effect shifts the rows of the character the  right,
with  the greatest displacement at the top.   This results in  the
appearance of italic text.   You should be aware that the VDI does
not  compensate for this effect.   This means that a skewed italic
character which is immediately followed by a normal blank will  be
overstruck,  and  part of the top of the character will disappear.
Likewise,  a  skewed character written to the left of an  existing
normal  character will overstrike part of it.   There is a related
bug  in  the VDI clipping logic which may cause some  parts  of  a
skewed  character not to be redrawn if they fall at the edge of  a
clipping  rectangle,  even  though  they should  fall  within  the
region.

     The  outline  effect  produces output which is  a  one  pixel
"halo" around the normal character.  The shadow effect attempts to
create  a  "drop  shadow" to the side  of  the  character.   These
effects  should be used very sparingly with default  sized  fonts.
They often result in illegible output.

     When  graphics text is written,  a screen coordinate must  be
specified  for  the output.   The relationship of the text to  the
screen point is determined by the call:

\begin{verbatim}
          vst_alignment(vdi_handle, hin, vin, &hout, &vout);
\end{verbatim}

{\tt hin}  and  {\tt vin} are each words,  with values specifying the  desired
horizontal  and vertical alignment,  respectively.   {\tt hout}\/ and
 {\tt vout}
receive the actual values set by the VDI.  If they differ from the
requested values, an error has occurred.

     {\tt in} may be set to zero for left justification, one for center
justification,  or  two  for right justification.   The coordinate
given when text is written becomes the "anchor point" as described
in the definitions above.  The default justification is left.

     {\tt vin} determines what reference line of the text is  positioned
at the output coordinate.  The selection values are:

\begin{description}
\item[0] baseline (default)
\item[1] half line
\item[2] ascent line
\item[3] bottom line
\item[4] descent line
\item[5] top line
\end{description}

     A  common combination of alignments is left (0) and top  line
(5).   This  mode guarantees that all text output will lie to  the
right and below the output coordinate.   This corresponds with the
AES object and \verb"GRECT" coordinate systems.

     Finally, the call to do the actual output is:

\begin{verbatim}
          v_gtext(vdi_handle, x, y, string);
\end{verbatim}

{\tt x}  and {\tt y} define the screen coordinate to be used as the  alignment
point.   {\tt string}  is  a pointer to a null terminated string,  which
must  be total eighty characters or less,  exclusive of the  null.
This limit is imposed by the size of the \verb"intin[]" array in the  VDI
binding.   Be  warned  that  it  is NOT checked  in  the  standard
binding!  Exceeding it may cause memory to be overwritten.

     One Inquire Function is useful with text output.  The call

\begin{verbatim}
          vqt_attributes(vdi_handle, attrib);
\end{verbatim}

reads  back the current attribute settings into the 10 word  array
\verb"attrib[]".   The  main  items  of interest  are  \verb"attrib[6]"  through
\verb"attrib[9]",  which contain the width and height of characters,  and
the  width and height of the character cell in the  current  font.
You  should  rely  on this function to  obtain  size  information,
rather  than using the output of the \verb"graf_handle()"  function.   On
the ST, \verb"graf_handle()" always returns sizes for the monochrome mode
system font, which will be incorrect in the color screen modes.

     \verb"Attrib[1]" will contain the current graphics text color as set
by  \verb"vst_color()".   \verb"Attrib[3]"  and \verb"[4]" contain the  horizontal  and
vertical alignment settings, respectively.  \verb"Attrib[5]" contains the
current writing mode, as set by \verb"vswr_mode()".

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Optimization}

The most common complaint about using bit maps
for character output is lack of speed.  This section suggests ways
to  speed  things up.   By adopting all of these methods,  you can
realize an improvement of two to three times in speed.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Byte alignment}

Since writing graphic text is essentially a
bit-blit operation,  characters which have "fringes",  that is, do
not  align  evenly with byte boundaries,  will suffer  performance
penalities.  The default system fonts in all resolutions of the ST
are  a  multiple of eight pixels wide,  so the problem reduces  to
assuring  that  each characters starts at a byte boundary  in  the
screen bit map.  This will be true if the horizontal pixel address
of the left edge of the character is evenly divisible by eight.

     Obviously,  byte  alignment  is easiest to enforce  when  the
horizontal justification is right or left.  Doing so with centered
text is possible, but requires adding padding blanks to odd length
strings.

     When  writing  text within windows,  it is helpful to  assure
that the edges of the window working area are byte aligned.  There
is  a section of code in the listing which shows a technique  for
converting  a  user requested window position and/or size  to  its
working   dimensions,   byte-aligning  the  width  and  horizontal
position, and computing the adjusted external window coordinates.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Writing Mode}

The fastest text output mode is replace.  All
other modes require reading in the target raster area and  merging
it  with  the  new information.   You may find that you  must  use
transparent or reverse transparent mode,  for instance,  to use or
preserve an underlying background color other than white.  In this
case,  you  can  still  do  some optimization by  filling  in  the
background color for the entire string with a \verb"v_bar()" call, rather
than doing it one character cell at a time.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Clipping}

VDI  output  always  proceeds  faster  when  the
clipping rectangle is turned off, and text output is no exception.
Remember  that  you  may only do this if you are  drawing  into  a
dialog box,  or into the interior of a window which you know is on
top.   (You  can  use  the \verb"WM_TOPPED" and  \verb"WM_NEWTOP"  messages  for
keeping track of the top window, or use the \verb"WF_TOP wind_get()" call
to  find the current top.)  In both of these cases,  you will know
the  width  of the drawing area,  and you can truncate the  output
string to fit exactly, rather than setting the clipping rectangle.
For this to work,  you must have used the byte alignment technique
to  assure  that the width of the writing area is  a  multiple  of
eight. The VDI will also run at the non-clipped speed  if
the  ENTIRE  string  to  be written is  within  the  current  clip
rectangle.  To compound the problem, there is a one-off bug in the
detection  algorithm  for  the right  edge.   That  is,  the  clip
rectangle  has to be one pixel BEYOND the right edge of  the  text
for the fast write to work.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Bindings}

The  normal binding for \verb"v_gtext()" is inefficient.
It copies the string which you supply character-by-character  into
\verb"intin[]" before it calls the VDI itself.  In many cases, it will be
more  efficient for your application to place characters  directly
into \verb"intin[]" and make the VDI trap call directly.   To give you a
start,  the  code  for  the standard \verb"v_gtext()"  binding  has  been
included in the listing.  When setting up \verb"intin[]", be sure not to
load  more  than  80 characters,  or you will probably  crash  the
system!

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Moving text}

When performing text editing on the screen, you
should  avoid rewriting the string under edit  whenever  possible.
It is always more efficient to use the raster operations to move a
string  to  the right or left,  assuming that you have obeyed  the
byte  alignment rule.    If you are deleting characters,  blit the
unchanged part of the screen to the left,  and overstrike the last
character  in the string with a blank.   If inserting  characters,
blit  the  trailing  portion of the string  to  the  right  before
writing in the new character.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{By the way$\ldots$}

     It turns out there is an undocumented feature in
Alcyon  C  which allows you to imbed assembly code  in-line.   Try
using:

\begin{verbatim}
     asm(".....");
\end{verbatim}

where the dots are replaced with an assembly instruction.  You get
one instruction per \verb"asm()",  one \verb"asm()" per line.


\newpage

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\section{Computer - Human Interface}

\centerline{\bf And now for something completely different!}

This chapter of ST Professional GEM will be devoted
to examining a few of the principles of computer/human interface
design, or "religion" as some would have it.  I'm going to start
with basic ergonomic laws, and try to draw some conclusions which
are fairly specific to designing for the ST.

     For those who did not pray for this topic, it seems fair to
explain why your diet of hard-core technical information has been
interrupted by a sermon!  As a motivater, we might consider why
some programs are said by reviewers to have a "hot" feel (and
hence sell well!) while others are "confusing" or "boring".

     Alan Kay has said that "user interface is theatre".  I think
we may be able to take it further, and suggest that a successful
program works a bit of magic, persuading the user to suspend his
disbelief and enter an imaginary world behind the screen, whether
it is the mathematical world of a spreadsheet, or the land of Pacman
pursued by ghosts.

     A reader of a novel or science fiction story also suspends
disbelief to participate in the work.  Bad grammar and clumsy plotting
by the author are jarring, and break down the illusion.  Similarly,
a programmer who fails to pay attention to making his interface
fast and consistent will annoy the user, and distract him from
whatever care has been lavished on the functional core of the program.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Credit where it's due}

  Before launching into the discussion
of user interface, I should mention that the general treatment and
many of the specific research results are drawn from Card, Newell,
and Moran's landmark book on the topic, which is cited at the end
of this chapter.  Any errors in interpretation and application to
GEM and the ST are entirely my own, however.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Fingertips}

  We'll start right at the user's fingers with the
basic equation governing positioning of the mouse, Fitt's Law,
which is given as

\begin{equation}
     T = I \cdot \log_2( \frac{D}{S} + \frac{1}{2})
\end{equation}

 where T is the amount of time to move to a target, D is the distance
of the target from the current position, and S is the size of the
target, stated in equivalent units.  $\log_2$ is the base 2 (binary)
logarithm function, and I is a proportionality constant, about
100 milliseconds per bit, which corresponds to the human's "clock
rate" for making incremental movements.

     We can squeeze an amazing amount of information out of this
formula when attempting to speed up an interface.  Since motion time
goes up with distance, we should arrange the screen with the
usual working area near the center, so the mouse will have to move
a smaller distance on average from a selected object to a menu or
panel.  Likewise, any items which are usually used together should
be placed together.

     The most common operations will have the greater impact on
speed, so they should be closest to the working area and perhaps
larger than other icons or menu entries.  If you want to have
all other operations take about the same time, then the targets
farthest from the working area should be larger, and those closer
may be proportionately smaller.

     Consider also the implications for dialogs.  Small check boxes
are out.  Large buttons which are easy to hit are in.  There should
be ample space between selectable items to allow for positioning
error.  Dangerous options should be widely separated from common
selections.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Muscles}

 Anyone who has used the ST Desktop for any period
of time has probably noticed that his fingers now know where to find
the File menu.  This phenomenon is sometimes called "muscle memory",
and its rate of onset is given by the Power Law of Practice:

\begin{equation}
     T(n) = T(1) \cdot {n^{-a}}
\end{equation}

where T(n) is the time on the nth trial, T(1) is the time on the
first trial, and a is approximately 0.4.

     This first thing to note about the Power Law is that it only
works if a target stays in the same place!  This should be a potent
argument against rearranging icons, menus, or dialogs without some
explicit request by the user.  The time to hit a target which moves
around arbitrarily will always be T(1)!

     In many cases, the Power Law will also work for sequences of
operations to even greater effect.  If you are a touch typist, you
can observe this effect by comparing how fast you can enter "the"
in comparison to three random letters.  We'll come back shortly
to consider what we can do to encourage this phenomenon.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Eyes}

  Just as fingers are the way the user sends data to the
computer, so the eyes are his channel from the machine.  The rate
at which information may be passed to the user is determined by
the "cycle time" of his visual processor.  Experimental results
show that this time ranges between 50 and 200 milliseconds.

     Events separated by 50 milliseconds or less are always
perceived as a single event.  Those separated by more than 200
milliseconds are always seen as separate.  We can use these
facts in optimizing user of the computer's power when driving the
interface.

     Suppose your application's interface contains an icon which
should be inverted when the mouse passes over it.  We now know
that flipping it within one twentieth of a second is necessary
and sufficient.  Therefore, if a "first cut" at the program achieves
this performance, there is no need for further optimization, unless
you want to interleave other operations.  If it falls short, it will
be necessary to do some assembly coding to achieve a smooth feel.

     On the other hand, two actions which you want to appear distinct
or convey two different pieces of information must be separated
by an absolute minimum of a fifth of a second, even assuming that
they occur in an identical location on which the user's attention
is already focused.

     We are able to influence the visual processing rate within the
50 to 200 millisecond range by changing the intensity of the stimulus
presented.  This can be done with color, by flashing a target, or
by more subtle enhancements such as bold face type.  For instance,
most people using GEM soon become accustomed to the "paper white"
background of most windows and dialogs.  A dialog which uses a
reverse color scheme, white letters on black, is visually shocking
in its starkness, and will immediately draw the user's eyes.

     It should be quickly added that stimulus enhancement will only
work when it unambiguously draws attention to the target.  Three or
four blinking objects scattered around the screen are confusing, and
worse than no enhancement at all!

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Short-term memory}

  Both the information gathered by the eyes
and movement commands on their way to the hand pass through short-term
memory (also called working memory).  The amount of information which
can be held in short-term memory at any one time is limited.  You can
demonstrate this limit on yourself by attempting to type a sheet of
random numbers by looking back and forth from the numbers to the
screen.  If you are like most people, you will be able to remember
between five and nine numbers at a time.  So universal is this
finding that it is sometimes called "the magic number seven, plus
or minus two".

     This short-term capacity sets a limit on the number of choices
which the user can be expected to grasp at once.  It suggests that
the number of independent choices in a menu, for instance, should
be around seven, and never exceed nine.  If this limit is violated,
then the user will have to take several glances, with pauses to
think, in order to make a choice.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Chunking}

  The effective capacity of short-term memory can be
increased when several related items are mentally grouped as a "chunk".
Humans automatically adopt this strategy to save themselves time.
For instance, random numbers had to be used instead of text in the
example above, because people do not type their native language as
individual characters.  Instead, they combine the letters into words
and remember these chunks instead.  Put another way, the characters
are no longer considered as individual choices.

     A well designed interface should promote the use of chunking
as a strategy by the user.  One easy way is to gather together
related options in a single place.  This is one reason that like
commands are grouped into a single menu which is hidden except for
its title.  If all of the menu options were "in the open", the user
would be overwhelmed with dozens of alternatives at once.  Instead, a
"Show Info" command, for instance, becomes two chunks: pick File
menu, then pick Show.

     Sometimes the interface can accomplish the chunking for the user.
Consider the difference between a slider bar in a GEM program, and
a three digit entry field in a text mode application.  Obviously,
the GEM user has fewer decisions to make in order to set the associated
variable.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Think!}

  While we are puttering around trying to speed up
the keyboard, the mouse, and the screen, the user is actually
trying to get some work done.  We need to back off now, and
look at the ways of thinking, or cognitive processes, that go into
accomplishing the job.

     The user's goal may be to enter and edit a letter, to retrieve
information from a database, or simply draw a picture, but it
probably has very little to do with programming.  In fact, the
Problem Space Principle says that the task can be described as
a set of states of knowledge, a set of operators and associated
constraints for changing the states, and the knowledge to
choose the appropriate operator, which resides in the user's head.

     Those with a background in systems theory can consider this
as a somewhat abstract, but straightforward, statement in terms of
state variables and operators.  A programmer might compare the
knowledge states to the values of variables, the operators to
arithmetic and logic operations, the constraints to the rules of
syntax, and the user's knowledge to the algorithm embodied by a
program.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Are we not men?}

  A rational person will try to attain his
goals (get the job done) by changing the state of his problem space
from its initial state to the goal state.  The initial state,
for instance, might be a blank word processor screen.  The desired
final state is to have a completed business letter on the screen.

     The Rationality Principle says that the user's behavior in
typing, mousing, and so on, can be explained by considering the
tasks required to achieve the goal, the operators available to
carry out the tasks, and the limitations on the user's knowledge,
observations, and processing capacity.  This sounds like the
typical user of a computer program must spend a good deal of time
scratching his head and wondering what to do next.  In fact, one
of Card and Moran's key results is that this is NOT what takes place.

     What happens, in fact, is that the trained user strikes a sort
of "modus vivendi" with his tool and adopts a set of repetitive,
trained behavior patterns as the best way to get the job done.
He may go so far as to ignore some functions of the program in
order to set up a reliable pattern.  What we are looking for is a
way of measuring and predicting the "quality" of this trained
behavior.  Since using computers is a human endeavor, we should
consider not only the speed with which the task is completed, but
the degree of annoyance or pleasure associated with the process.

     Card and Moran constructed a series of behavioral models which
they called GOMS models, for Goals-Operators-Methods-Selection.
These models suggested that in the training process the user
learned to combine the basic operators in sequences (chunks!)
which then became methods for reaching the goals.  Then these
first level methods might be combined again into second level
methods, and so forth, as the learning progressed.

     The GOMS models were tested in a lengthy series of trials
at Xerox PARC using a variety of word processing software.  (Among
the subjects of these experiments were the inventors of
the windowing methods used in GEM!)  The results were again
surprising: the level of detail in the models was really unimportant!

     It turned out to be sufficient to merely count up the number
of keystrokes, mouse movements, and thought intervals required
by each task.  After summing up all of the tasks, any extra time
for the computer to respond, or the user to move his hands from
keyboard to mouse, or eyes from screen to printed page is added in.
This simplified version is called the Keystroke-Level Model.

     As an example of the Keystroke Model, consider the task of
changing a mistyped letter on the screen of a GEM word processor.
This might be broken down as follows: 

\begin{enumerate}
        \item find the letter on the screen;
        \item move hand to mouse;
        \item point to letter;
        \item click mouse button;
        \item move hand to keyboard;
        \item strike {\tt Delete} key;
        \item strike key for new character.
\end{enumerate}

     The sufficiency of the Keystroke Model is great news for our
attempt to design faster interfaces.  It says we can concentrate
our efforts on minimizing the number of total actions to be taken,
and making sure that each action is as fast as possible.  We have
already discussed some ways to speed up the mouse and keyboard
actions, so let's now consider how to speed up the thought intervals,
and cut the number of actions.

     One way to cut down "think time" is to make sure that the
capacity of short-term memory is not exceeded during the course of
a task.  For example, the fix-a-letter task described above required
the user to remember:

\begin{enumerate}
        \item his place in the overall job of typing the document;
        \item the task he is about to perform;
        \item where the bad character appeared, and
        \item what the new character was.
\end{enumerate}

When this total of items creeps toward seven, the user often loses his place
and commits errors.

     You can appreciate the ubiquity of this problem by considering
how many times you have made mistakes nesting parentheses,
or had to go back to count them, because too many things happened
while typing the line to remember the nesting levels. The moral is that
operations with long strings of operands should be avoided when
designing an interface.

     The single most important factor in making an interface
comfortable to use is increasing its predictability, and
decreasing the amount of indecision present at each step during
a task.  There is (inevitably) an Uncertainty Principle which
relates the number of choices at each step to the associated
time for thought:

\begin{equation}
     T = I \cdot \log_2 ( N + 1 )
\end{equation}

 where LOG2 is the binary logarithm function, N is the number of
equally probable choices, and I is a constant of approximately
140 msec/bit.  When the alternates are not equally probable, the
function is more complex:

\begin{equation}
     T = I \cdot \sum_{i=1}^N P(i) \cdot \log_2 ( \frac{1}{P(i)+1} )
\end{equation}

 where the P(i) are the probabilities of each of the choices (which
must sum to one).  Those of you with some information theory
background will recognize this formula as the entropy of
the decision; we'll come back to that later.

     So what can we learn from this hash?  It turns out, as we might
expect, that we can decrease the decision time by making some
of the user's choices more probable than others.  We do that by
means of feedback cues from the interface.

     The importance of reliable, continuous meaningful feedback
cannot be emphasized enough.  It helps the beginner learn the system,
and its predictability makes the program comfortable for the expert.
Programs with no feedback, or unreliable cues, produce confusion,
dissonance, and frustration in the user.

     This principle is so important that I going to give several
examples from common GEM practice.  The Desktop provides several
instances.  When an object is selected and a menu drops down, only
those choices which are legal for the object are in black.  The
others are dimmed to grey, and are therefore removed from the
decision.  When a pick is made from the menu, the bar entry remains
black until the operation is complete, reassuring the user that
the correct choice was made.  In both the Desktop and the RCS,
items which are double-clicked open up with a "zoom box" from
the object, again showing that the right object was picked.

     Other techniques are useful when operator icons are exposed on
the screen.  When an object is picked, the legal operations might
be outlined, or the bad choices might be dimmed.  If the screen
flashing produced by this is objectionable, the legal icons can
be made mouse sensitive, so they will "light up" when the cursor
passes over - again showing the user which choices are legal.

     The desire for feedback is so strong that it should be provided
even while the computer is doing an operation on its own.  The hour
glass mouse form is a primitive example of this.  More sophisticated
are "progress indicators" such as animated thermometer bars,
clocks, or text displays of the processing steps.  The ST Desktop
provides examples in the Format and Disk Copy functions.  The purpose
of all of these is to reassure the user that the operation is
progressing normally.  Their lack can lead to amusing spectacles
such as secretaries leaning over to hear if their disk drives are
working!

     Another commonly overlooked feature is error prevention and
correction.  Card and Moran's results showed that in order to go
faster, people will tolerate error rates of up to 30% in their
work.  Any program which does not give a fast way to fix mistakes
will be frustrating indeed!

     The best way to cope with an error is to "make it didn't happen",
to quote a common child's phrase.  The same feedback methods
discussed above are also effective in preventing the user from
picking inappropriate combinations of objects and operations.
Replacement of numeric type-ins with sliders or other visual
controls eliminates the common "Range Error".  The use of radio
buttons prevents the user from picking incompatible options.
When such techniques are used consistently, the beginner also
gains confidence that he may explore the program without blundering
into errors.

     Once an error has occured, the best solution is to have an
"inverse operation" immediately available.  For instance, the way
to fix a bad character is to hit the backspace key.  If a line is
inadvertantly deleted, there should be a way to restore it.

     Sometimes the mechanics of providing true inverses are
impractical, or end up cluttering the interface themselves.  In
these cases, a global "Undo" command should be provided to
reverse the effect of the last operation, no matter what it was.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Of modes and bandwidth}

  Now I am going to depart from
the Card, Newell and Moran thread of discussion to consider
how we can minimize the number of operations in a task by
altering the modes of the interface.  Although "no modes" has
been a watchword of Macintosh developers, the term may need
definition for Atarians.

     Simply stated, a mode exists any time you cannot get to
all of the capabilities of the program without taking some
intermediate step.  Familiar examples are old-style "menu-driven"
programs, in which user must make selections from a number of
nested menus in order to perform any operation.  The options
of any one menu are unavailable from the others.

     Recall that the user is trying to accomplish work in his
own problem space, by altering its states.  A mode in the
program adds additional states to the problem space, which he is
forced to consider in order to get the job done.  We might call
an interface which is completely modeless "transparent", because it
adds no states between the user and his work.  One of the best
examples of a transparent program is the 15-puzzle in the Macintosh
desk accessory set.  The problem space of rearranging the tiles
is identical between the program and a physical puzzle.

     Unfortunately, most programmers find themselves forced to
put modes of some sort into their programs.  These often arise
due to technological limitations, such as memory space, screen
"real estate", or performance limitations of peripherals.  The
question is how the modes can be made least offensive.

     I will make the general claim that the frustration which a
mode produces is directly proportional to the amount of the user's
bandwidth which it consumes.  In other words, we need to consider
how many keystrokes, mouse clicks, eye movements, and so on, are
going into manipulating the true problem states, and how many
are being absorbed by the modes of the program.  If the interface
is wasting a large amount of the user's effort, it will be perceived
as slow and annoying.

     Here we can consider again the hierarchy of goals and methods
which the user employs.  When the mode is low in the hierarchy,
and close to the user's "fingertips", it is encountered the most
frequently.  For instance, consider how frustrating it would be
to have to hit a function key before typing in each character!

     The "menu-driven" style of programs mentioned above are
almost as bad, since usually only one piece of information is
collected at each menu.  Such a program becomes a labyrinth of
states better suited to an adventure game!

     The least offensive modes are found at the higher, goal
related levels of the hierarchy.  The better they align with
changes in the state of the original problem, the more they
are tolerated.  For example, a word processing program might
have one screen layout for program editing, another for writing
letters, and yet another while printing the documents.  A
multi-function business package might have one set of menus for
the spreadsheet, another for a graphing module, and a third
for a database.

     In some cases the problem solved by the program has convenient
"fracture lines" which can be used to define the modes.  An
example in my own past is the RCS, where the editing of each
type of resource tree forms its own mode, with each of the modes
nested within the overall mode and problem of composing the
entire resource tree.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{To do is to be!}

  Any narrative description of user interface
is bound to be lacking.  There is no way text can convey the vibrancy
and tactile pleasure of a good interface, or the sullen boredom
of a bad one.  Therefore, I encourage you to experiment.  Get out
your favorite arcade game and see if you can spot some of the
elements I have described.  Dig into your slush pile for the most
annoying program you have ever seen, run it and see if you can see
mistakes.  How would you fix them?  Then... go do it to your own
program!

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\newpage
\section{More User Psychology}

This chapter continues the discussion of user interface design. It begins
where we left off, with a further treatment of the mode problem, and
proceeds into topics such as visual grammar and layered interfaces.

\subsection{Modes Again}

If a program is modeless, it acts predictably, which turns out to be 
very important. On the other hand, a good definition for ``modes'' is hard 
to find. In the previous chapter I suggested that a mode exists when you cannot 
use all of the capabilities of the program without performing some 
intermediate step. If this is less than clear, here are two alternate 
definitions offering different views of the problem.

The "TWO USER TEST". Consider the following thought experiment: Imagine 
that your ST (and GEM) had two mice, two cursors, and two users. Could 
they both effectively use the program at the same time? If so, the 
application is modeless. If there are points where one user can be 
``locked out'' by the actions of the other, then a mode exists at that 
point. Let's consider some examples of this test.

In any program which uses the GEM menu system, one user could stop the 
other by touching a menu hotspot and dropping a menu. This constitutes 
an inherent mode in the GEM architecture.

On the GEM Desktop, two users could open windows and view files without 
interference. However, as soon as one person tries to delete a file 
(assuming the verify option is on), the other is brought to a halt as a 
dialog appears. Thus, we have found a modal dialog.

In many "Paint-type" programs, such as MacPaint, PC Paint, and GEM 
Paint, two artists could co-exist quite well, utilizing the on-screen 
palette and tool selection. Of course, these programs also contain modal 
dialogs for such operations as file and brush shape selection. In 
contrast, consider the paint program DEGAS for the ST. Here, two artists 
could only work together as long as neither wanted to change tool or 
color. Then the display would have to be flipped to the selection 
screen, stopping the other user. This is a mode in the DEGAS interface.

(By the way, this test is not just academic. The grand-daddy of all 
mouse based systems, NLS, demonstrated by Doug Englebart in 1968, had 
two mice and two users, one of whom was physically remote. Cooperative 
techniques such as this are still largely unexplored and unexploited.)


\subsection{One Liner}

Here's a terse definition by Jef Raskin: A program is modeless if a 
given action has one and only one result. Again, let's run a few 
examples.

The menu dropdowns are clearly modal by this definition. Before the menu 
was activated, window control points could be activated with a click. 
However, when the dropdown is visible, a click action is interpreted as 
a menu selection or a dismissal of the dropdown. Similarly, dialogs are 
modal because the action of moving the mouse into the menu bar no longer 
causes the dropdown to appear.

I am typing this using the First Word editor program. It has a nice 
desktop level box full of characters where I can click to get symbols 
which the ST keyboard won't produce. However, if I invoke the find or 
replace string dialog, the click-in-the-box action doesn't work anymore. 
This is a mode in the First Word interface.

Finally, consider an "old style" menu program, the kind where you type 
in the number of the desired action from a list. Since the number "2" 
might mean "Insert the record" in one menu, and "Purge the file" in 
another, such a program is clearly modal by Raskin's definition.

These three definitions say almost the same thing, but from different 
viewpoints. Depending on the situation, one or the other may be more 
intuitive for you. The goal of this type of analysis is to root out 
unnecessary modes, and to make sure that those which remain only appear 
when requested by the user, offer some visual cue such as a rubber line 
or standard dialog box, and are used consistently throughout the 
application.


\subsection{Predictability Forever And Ever}

As Raskin's definition makes clear, when the modes go away, the 
interface becomes predictable. Predictability leads to the formation of 
habits of use. Habits reduce "think time" and become progressively 
faster due to the Power Law of Practice I have discussed. This 
is exactly what we want!

There is another benefit of predictability. A habit learned in one part 
of a program with a consistent interface can be transferred and used 
elsewhere in the application. If several programs share the same style 
of interface, the same habits can be used across a complete set of 
products. Learning time for the new functions becomes shorter, and the 
user is more likely to use the new feature.


\subsection{It's A Bogeyman!}

Most casual users are scared silly of computers and programs. (If you 
have any doubt, eavesdrop on a secretary with a new word processor, or 
the doctor's receptionist coping with an insurance data entry program.) 
In most cases, they have a right to be frightened. Even experienced 
programmers, prone to toss the manuals and hack away, know that moderate 
paranoia is the best way to deal with an unknown program. How must this 
feel to someone whose ability to perform (or lose) their job depends on 
an unpredictable (aha!) black box.

So here's another way in which predictability works. But to produce a 
truly fearless user, we need other qualities as well. One is robustness, 
meaning that the program will not crash given normal or even bizarre 
actions by the user. Another is feedback, which shuts off invalid 
options, reinforces correct actions, and gives reassurance that an 
operation is proceeding normally. Finally, we need forgiveness, in the 
form of inverse operations or Undo options, when the inevitable mistake 
is made.

The ultimate goal is make the program discoverable. This means the user 
should be able to safely "wing it" after a short session with the 
application and its interface. This practice ought to be considered the 
norm anyway, since the manual is always across the office or missing 
when an esoteric and half-forgotten feature is needed. If it is possible 
to muddle through such a situation by trial and error, without causing 
damage, the immediate problem will be solved, and the user will gain 
confidence.


\subsection{Good Grammar Or...}

So exactly what are these habits that are supposed to be so helpful? One 
of the most useful patterns is a consistent command grammar for the 
program. This may sound strange, since we have supposedly abandoned 
command line interfaces in the graphics world, but in fact, the same 
type of rules apply. For instance, in the world of \verb"A>" we might issue the 
command:

\begin{verbatim}
    copy a:foobar.txt b:
\end{verbatim}

By analogy to Englist grammar, this command contains a verb, \verb"copy", a 
file as subject: \verb"a:foobar.txt", and a location as an object: \verb"b:". The 
equivalent GEM Desktop operation is:

\begin{enumerate}
\item 	Move mouse to {\tt foobar.txt} icon in {\tt a:} window
\item 	Press mouse button
\item 	Move mouse to {\tt b:} icon
\item 	Release mouse button
\end{enumerate}

The operation can be described as a select-drag-drop sequence, with the 
select designating the subject file, the drag denoting the operation 
(copy), and the location of the drop showing the object. A grammar still 
exists, but its "terminal symbols" are composed of mouse actions 
interpreted in the context of the current screen display, rather than 
typed characters.

One useful way to analyze simple grammars, including those used as 
command languages, is to separate them into prefix, postfix, and infix 
forms. In a prefix grammer, the operation to be performed precedes its 
operands, that is, its subject(s) and object(s). The DOS copy command 
given above is an example of a prefix command. LISP is an example of a 
language which uses prefix specification for its commands.

Postfix grammars specify the action after all of the operands have been 
given. This command pattern is familiar to many as the way in which 
Hewlett-Packard calculators work. FORTH is an example of a language 
which uses a postfix grammar.

Infix notation places the verb, or operator, between its subject and 
object. Conventional algebraic notation is infix, as are most computer 
languages such as C or PASCAL. The example GEM command given above is 
also infix, since the selection of a subject file preceded the action, 
which was followed by the designation of an object.

The "standard" GEM command grammar, as used in the products produced by 
Digital Research, is in fact infix. This is not to say that GEM enforces 
such a convention, or that it is rigorously followed. However, when 
there is no pressing reason for a change, adoption of an infix command 
grammar will make your application feel most like others which users may 
have seen.

The general problem of specifying a graphic command language can be 
difficult, but much of the problem has already been handled on the ST. 
Part of the solution is by constraint: the input and output hardware of 
the ST are predefined, so most developers will not need to worry about 
choosing a pointing device or screen resolution. The other part of the 
standard solution is the GEM convention for mouse usage. I am going to 
review these rules, and then describe of the situations in which they 
have been bent, and finally some alternate approaches which may prove 
useful to some developers.

\subsection{Specifying A Subject}

There are really two sets of methods for designating what is to be 
affected by an operation. One set is used when distinct objects are to 
be affected. Examples are file and disk icons in the Desktop and trees 
in the RCS. Another set of designation methods is used when continuous 
material, such as text or bit images, is being handled.

When dealing with objects, a single mouse click (down and up) over the 
object selects it. The application should show that the selection has 
occurred by changing the appearance of the object. The most common 
methods are inverting the object, or drawing "handles" around it.

Many operations allow "plural", or multiple object, selections. The GEM 
convention is that a click on an object while the shift key is held down 
extends the selection by adding that object. If the shift-clicked object 
was already selected, it is deleted from the selection list.

Another way to select multiple objects is to use a "rubber box" to 
enclose them. This operation begins with drag on a part of the view 
where no object is present. The application then animates a rubber box 
on the screen as long as the mouse button is held down. When the button 
is released, all objects within the current extent of the box are 
selected. A shift-drag combination could be used to add the objects to 
an existing selection list.

Selecting part of a text or bit plane display is also done with a rubber 
box. Since there are no "objects" in the view, any mouse drag is 
interpreted as the beginning of a selection operation. In the simplest 
case, a bit plane, the rectangle within the box when the button is 
released is the selected extent.

When the underlying data has structure, such as words and lines of text, 
the display should reflect this fact during the selection operation. 
Typically, text selection is indicated by inversion of the characters 
rather than a rubber box. The selection extends along the starting line 
so long as the mouse stays within the line. If the mouse move off the 
starting text line, the implied selection is all characters between the 
starting character and the character currently under the mouse, which is 
not necessarily a rectangular area.

An extended "plural" selection may be supported in text editing. The use 
of the shift key is also conventional in this application.


\subsection{Action}

With the subject designated, the user can now choose an operation. In 
many cases, this will be picked from the menu, in which case the entire 
command is complete. Some menu selections will lead to dialogs, in which 
the interaction methods are regulated by the GEM form manager. When the 
command is completed, it is often helpful if the application leaves the 
objects (or areas) selected and ready for another operation. A single 
click away from any object is interpreted as cancelling the selections.

Many operations are indicated by gestures on the screen. Usually, this 
is some variant of a drag operation. The interpretation of the gesture 
may depend on the type and location of the selected subject, which part 
of it is under the mouse, and in what location the drag terminates.

"Handles" are small boxes or dot displayed around an object when it is 
selected. A drag beginning with the mouse on a handle is usually 
interpreted as a resizing operation, if this is appropriate. The 
pointing finger mouse form is displayed to indicate the operation in 
progress, and a rubber version of the object is animated on the screen 
to show the user the result if the button were released. In some cases, 
where an underlying "snap" grid exists, the animated object may change 
size in discrete steps.

Dragging a non-handle area of a selected object is usually interpreted 
as the beginning of a move function. In most applications, a move of a 
single object may be started without pre-selection. Simply beginning the 
drag on the object is taken to imply selection. The spread hand, or 
"grabber", mouse form is typically displayed during a drag operation.

Dragging may denote copying or movement, or more complex functions such 
as instantiation or generalization. The operation implied by movement on 
the screen will differ among applications, and often within the same 
application, depending on target location. This target is the recipient 
of the command's action, or its object, in an English grammar sense.

For example, a drag from window to window in the Desktop denotes a copy. 
On the other hand, dragging the same icon to the trashcan deletes it 
completely. Dragging an object from the RCS partbox to the editing view 
creates a new copy of that prototype object. Dragging the same object 
within the edit view simply changes its placement.

There are some mouse actions which are conventional "abbreviations". A 
double click on an object is interpreted as both a selection and an 
action. Usually, the double click action is the same as the Open entry 
in the "File" menu.

When the usual interpretation of a drag is movement, then shift-drag may 
be used as an enhanced varient implying copying. For instance, shift-
dragging an object within the RCS editing window makes a copy of the 
object and places it in the final location.

To return to the beginning of this discussion, the reason for adopting 
these conventional usages is to build an interface that promotes habits. 
Particularly, a standard grammar for giving commands helps answer the 
question "What comes next?". It breaks the user's actions into logical 
phrases, or chunks, which may be thought of a whole, rather than one 
action at a time.

\subsection{Different Folks, Different Strokes}

There are always exceptions to a rule, or so it seems. In this case, 
consistency of the interface grammar is sometimes traded off against 
consistency of metaphor, preservation of screen space, and "fast path" 
methods for experts.

One example is the use of "tools" in Paint and Draw programs. In such 
programs, an initial click is made on a tool icon, denoting the 
operation to be applied to all following selections. This is an prefix 
style of grammar, and stands in contrast to the usual method of 
selecting subject object(s) first. Because of this contrast, it is 
sometimes called "moding the cursor". (Try applying the tests above to 
be sure it really is a mode.)

In these cases, there are two reasons for accepting the nonstandard 
method. The first is consistency of metaphor. The "user model" portrayed 
in the programs is an artist's work table, with tools, palette, and so 
on. The cursor moding action is equivalent to picking up a working tool. 
The second reason is speed. In a Paint program, the "canvas" is often 
modified, and speed in creating or changing the bits is important. In 
more object oriented applications such as Desktop or RCS, the objects 
are more persistent. Speed is then more essential when adding or 
changing properties of the objects.

When command styles are mixed in this fashion, you must design very 
carefully to avoid conflicts or apparent side-effects in the command 
language. For example, in GEM Draw picking an action from the Edit menu 
cancels the current cursor mode without warning. Confusion from such 
side-effects may cancel out the benefits of the mixed grammar.

The subject of command further attention. While the novice approaching a 
program needs full feedback, a person who uses it day in and day out 
will learn the program, and want faster ways to get the job done, even 
if they are more arcane. The gives rise to a "layered" style of 
interface.

A layered interface is designed so that the visual grammar is obvious, 
as we have discussed. However, there are one or more sets of 
"accelerators" built into the program, which may be harder to find but 
faster to use. One example is condensed mouse actions such as the 
double-click. For instance, attempting to select a block of text which 
extends beyond a window is impossible using the basic metaphor. The 
novice will simply do the operation in pieces. A layered interface might 
put a less obvious Mark Begin and Mark End option in the menus. Another 
way is to take a drag which extends outside the window as a request to 
begin scrolling in that direction, while extending the current 
selection.

One of the most common and useful accelerator methods is function keys. 
Using this approach, single key equivalents to actions are listed in the 
menu. Striking this key when an object is selected will cause the action 
to occur. Note that this is most useful if some keyboard driven method 
of object selection, such as tabbing, is also available. Otherwise, the 
time switching from the mouse, used to select the object, to the 
keyboard for command input, may well cancel any advantage.

Finally, radical departures from the GEM metaphor may be useful when 
attempting to replicate the look of another system, or trying to meet 
severe constraints, such as display space. One example would be 
discarding the standard GEM menus in favor of "popup" menus which appear 
next to the current mouse position in response to a click on the second 
button. This method has the advantage of preserving the menu space at 
the top of the screen, and is potentially faster because the menu 
appears right next to the current mouse position. The drawbacks are lack 
of a visual cue for naive users trying to find the commands, and the 
need for custom coding to build the popups.


\subsection{More To Come}

We have reached the end of the second sermon on user interface. In a 
future chapter, I will look at "higher level" topics relating to the 
design of the application's user metaphor. These include issues of 
object orientation, direct manipulation, and the construction of 
microworlds. In the meantime, several of the more practical columns will 
present implementions of techniques such as accelarator keys and popup 
menus which I have discussed this time.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{References}

  Stuart K.~Card, Thomas P.~Moran, and Allen Newell:
 {\em The Psychology of Human-Computer Interaction}, Lawrence
Erlbaum Associates, Hillsdale, New Jersey, 1983.  (Fundamental
and indispensible.  The volume of experimental results make it
weighty.  The Good Parts are at the beginning and end.)

     {\em Macintosh User Interface Guidelines}, in Inside Macintosh,
Apple Computer, Inc., 1984.  (Yes, Atarians, we have something to
learn here.  Though not everything "translates", this is a fine
piece of principled design work.  Read and appreciate.)

     James D.~Foley, Victor L.~Wallace, and Peggy Chan,
{\em The Human Factors of Computer Graphics Interaction Techniques},
IEEE Computer Graphics (CG \& A), November 1984, pp. 13--48.
(A good overview, including higher level topics which I have
postponed to a upcoming later section.  Excellent bibliography.)

     J.~D.~Foley and A.~Van Dam,
{\em Fundamentals of Interactive Computer Graphics},
Addison Wesley, 1984, Chapters 5 and 6.
(If you can't get the article above, read this.  If you are designing
graphics apps, buy the whole book!  Staggering bibliography.)

     Ben Schneidermann, {\em Direct Manipulation: A Step Beyond
Programming Languages}, IEEE Computer, August 1983, pp. 57--69.
(What do Pacman and Visicalc have in common?  Schneidermann's
analysis is vital to creating hot interfaces.)


\newpage

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\section{GEM Events and Program Structure}

     So I fibbed a little.  This chapter of ST Professional GEM started
out to be another discussion of interface issues.  But, as Tolkien
once said, the tale grew in the telling, and this is now the first
of  a series of three articles.   This part will discuss AES event
handling  and  its implications for GEM  program  structure.   The
following  will contain a "home brew" dialog handler  with
some  new  features,  and  will,  finally,  take up  the
discussion  of  interface design,  using the dialog handler as  an
example. 

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{All for one, and one for all}

  A quick inspection of the AES
documents  shows that there are five routines devoted  to  waiting
for individual types of events, and one routine, \verb"evnt_multi", which
is  used  when more than one type is desired.   This article  will
discuss  ONLY \verb"evnt_multi" for two reasons.   First,  it is the most
frequently used of the routines.   Second, waiting for one type of
event is a bad practice.   Any event call turns the system over to
the AES and suspends the application and its interaction with  the
user.   In  such  cases,  some  "escape clause",  such as a timer,
should be inserted to revive the program and prompt the user if no
event  is  forthcoming.   Otherwise,  the  application may end  up
apparently  (or  actually)  hung,  with a  resulting  reboot,  and
probably a very annoyed user.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Starting ahead}

One  possible type of event is a  message.
Messages  are usually sent to the application by the AES,  and are
associated  with  windows or the menu.   We have already
discussed such messages:
we considered  window  messages,  and we   handled  menu
messages.  You may want to review these topics before proceeding.

     The actual \verb"evnt_multi" call is a horrendous thing:

\begin{verbatim}
     ev_which = evnt_multi(ev_flags,
               btn_clicks, btn_mask, btn_state,
               r1_flags, r1_x, r1_y, r1_w, r1_h,
               r2_flags, r2_x, r2_y, r2_w, r2_h,
               &msg_buff,
               time_lo, time_hi,
               &mx, &my, &btn, &kbd, &char, &clicks);
\end{verbatim}

Each  of  the lines in the call relate to a different  event,  and
they  will be discussed in the order in which they  appear.

     Note  that a call with this number of parameters causes  some
overhead  due  to stacking and retrieval of the values.   In  most
cases,  this  should be of little concern on a machine as fast  as
the ST.   However, where throughput is a concern, such as in close
tracking  of the mouse cursor,  you may want to write a customized
binding  for \verb"evnt_multi" which dispenses with the  parameter  list.
This  can  be accomplished by maintaining the values in  a  static
array  and moving them as a block into the binding  arrays  \verb"int_in"
(for all values but \verb"&msg_buff"), and \verb"addr_in" (for \verb"&msg_buff").  Note
that  you  may {\em not}\/ simply leave the values in \verb"int_in";  other  AES
bindings reuse this space.

     {\tt ev\_flags}  and {\tt ev\_which} are both 16-bit integers  composed  of
flag bits.  Bits set in {\tt ev\_flags}\/ determine which event(s) the call
will  wait  for;  those  set in {\tt ev\_which}\/  indicate  what  event(s)
actually occurred.   Both use the following flag bit mnemonics and
functions:

\vskip.5cm
\begin{center}
\begin{tabular}{c|l}
     0x0001 & {\tt MU\_KEYBD} --- Keyboard input\\
     0x0002 & {\tt MU\_BUTTON} --- Mouse button(s)\\
     0x0004 & {\tt MU\_M1} --- Mouse rectangle \#1\\
     0x0008 & {\tt MU\_M2} --- Mouse rectangle \#2\\
     0x0010 & {\tt MU\_MESAG} --- AES message\\
     0x0020 & {\tt MU\_TIMER} --- Timer\\
\end{tabular}
\end{center}
\vskip.5cm

The  appropriate mnemonics are ORed together to create the  proper
{\tt ev\_flags}\/ value.

     There  is  one  common pitfall here.   Notice  that  multiple
events  may  be reported from one \verb"evnt_multi".   Event  merging  is
performed  by the AES in order to save space on the  application's
event queue.   If events have been merged,  more than one bit will
be  set in the {\tt ev\_which}\/ word.   Your application must check ALL of
the  bits  before  returning to a new  {\tt evnt\_multi}\/  call.   If  you
don't do this, some events may be effectively lost.

     The  first event to be considered is the mouse button.   This
is probably the most difficult event to understand and use.

     The  parameter  {\tt btn\_clicks} tells GEM the  maximum  number  of
clicks which you are interested in seeing.   This value is usually
two,  if your program uses the double-click method, or one if only
single  clicks  are used.   The AES returns the number  of  clicks
which caused the event through {\tt \&clicks}, which must be a pointer to
a word.

     GEM determines the number of clicks by the following  method.
When the first button-down is detected, a time delay is begun.  If
another  complete button-up,  button-down cycle is detected before
the time expires,  then the result is a double click.   Otherwise,
the  event is a single click.    Note that the final state of  the
buttons  is  returned via {\tt \&btn},  as described below.   By checking
this  final state,  you may determine whether a single click event
ended with the button up (a full click),  or with the button still
down  (which  may  be  interpreted as  the  beginning  of  a  drag
operation).   Double clicking is meaningless,  and not checked, if
the \verb"evnt_multi" is waiting on more than one button (see below).

     The double-click detection delay is variable,  and may be set
by your program using the call

\begin{verbatim}
     ev_dspeed = ev_dclick(ev_dnew, ev_dfunc);
\end{verbatim}

{\tt ev\_dfunc}\/  is a flag which determines the purpose of the call.   If
it  is  zero,  the  current  double click  speed  is  returned  in
{\tt ev\_dspeed}\/.   If {\tt ev\_dfunc}\/ is non-zero, then {\tt ev\_dnew}\/
becomes the new double-click   speed. Both {\tt ev\_dspeed}\/  and 
{\tt ev\_dnew}\/  are  words containing  a {\tt magic number}\/ between
zero and four.   Zero is  the
slowest  (i.e.,  longest)  double-click,  and four is the fastest.
(These  correspond  to  the  slow-fast  range  in  the   Desktop's
Preferences  dialog.)  In general,  you should not reset the click
speed  unless  specifically requested,  because such a change  can
throw off the user's timing and destroy the hand/eye  coordination
involved in using the mouse.

     GEM  was  originally designed to work with  a  single  button
input device.   This allows GEM applications to function well with
devices such as light pens and digitizing tablets.   However, some
features are available for dealing with multi-button mice like the
ST's.

     The  \verb"evnt_multi" parameters {\tt btn\_mask}\/ and {\tt btn\_state}\/  are  words
containing  flag bits corresponding to buttons.   The lowest order
bit corresponds to the left-most button,  and so on.  A bit is set
in  the  {\tt btn\_mask}\/ parameter if the AES is to  watch  a  particular
button.   The  corresponding bit in {\tt btn\_state}\/ is set to the  value
for  which  the program is waiting.   The word returned  via  {\tt \&btn}\/
uses  the  same  bit system to show the state of  the  buttons  at
completion.   It  is  important to notice that all of  the  target
states in {\tt btn\_state}\/ must occur {\em simultaneously}\/ for the event to  be
triggered.

     Note the limiting nature of this last statement.  It prevents
a  program from waiting for {\em either}\/ the left or right button to  be
pressed.  Instead, it must wait for {\em both}\/ to be pressed or to
be released, which is a
difficult  operation  at best.   As a result,  many people thought
the standard  mouse
button  procedure is practically useless if you want to take  full
advantage  of  both buttons on the ST mouse. 

     Fortunately there is a way out. If the upper byte of  {\tt btn\_clicks}
is set to one (by adding 256 to {\tt btn\_clicks}) the mouse event AES waits
for can be negated. So instead of waiting for "both mouse buttons released"
AES will wait for "NOT both mouse buttons released" which is actually
"one of the mouse buttons pressed". By reading  {\tt \&btn} we can then
easily determine which button was pressed. So setting  {\tt btn\_clicks})
to 256+2,  {\tt btn\_mask}) to 3 and  {\tt btn\_state}) to 0 will do the
trick!

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Mouse Rectangles}

One of GEM's nicer features is its ability
to watch the mouse pointer's position for you, and report an event
only  when it enters or departs a given screen region.   Since you
don't  have to track the mouse pixel by pixel,  this eliminates  a
lot  of application overhead.   The \verb"evnt_multi" call gives you  the
ability  to  specify one or two rectangular areas  which  will  be
watched.   An event can be generated either when the mouse pointer
enters the rectangle,  or when it leaves the rectangle.  The "r1\_"
series  of  parameters specifies one of the  rectangles,  and  the
"r2\_" series specifies the other, as follows:

\vskip.5cm
\begin{center}
\begin{tabular}{r|l}
     r1\_flag, r2\_flag & zero if waiting to enter rectangle,\\
                        & one if waiting to leave rectangle\\
     r1\_x, r2\_x & upper left X raster coordinate of wait rectangle\\
     r1\_y, r2\_y & upper left Y raster coordinate of wait rectangle\\
     r1\_w, r2\_w & width of wait rectangle in pixels\\
     r1\_h, r2\_h & height of wait rectangle in pixels
\end{tabular}
\end{center}
\vskip.5cm

Each  rectangle  wait will only be active if its  associated  flag
(\verb"MU_M1" or \verb"MU_M2") was set in {\tt ev\_flags}\/.

     There  are two common uses of rectangle waits.   The first is
used when creating mouse-sensitive regions on the screen.   Mouse-
sensitive regions, also called "hot spots", are objects which show
a  visual effect,  such as inversion or outlining,  when the mouse
cursor  moves  over them.   The items in a menu dropdown,  or  the
inversion  of  Desktop icons during a drag operation,  are  common
examples.

        Hot spots are commonly created by grouping  the  sensitive
objects  into  one  or  two areas,  and then setting  up  a  mouse
rectangle  wait  for  entering  the  area.    When  the  event  is
generated,  the  {\tt \&mx}  and {\tt \&my} returns may be examined to find  the
true  mouse coordinates,  and \verb"objc_find" or some other search  will
determine  the affected object.   The object is then  highlighted,
and  a new wait for exiting the object rectangle is  posted.

     The  second common use of rectangle waits is in  animating  a
drag operation.  In many cases, you can use standard AES animation
routines such as \verb"graf_dragbox" or \verb"graf_rubberbox".   In other cases,
you  may  want  a figure other than a simple  box,  or  desire  to
combine   waits  for  other  conditions  such  as  keystrokes   or
collision with hotspots.  Then you will need to implement the drag
operation  yourself,  using  the  mouse rectangles  to  track  the
cursor.

     If you want to track the cursor closely, simply wait for exit
on a one pixel rectangle at the current position,  and perform the
animation routine at each event.  If the drag operation only works
on a grid,  such as character positions,  you can specify a larger
wait  rectangle and only update the display when a legal  boundary
is crossed.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Messages}

The  {\tt \&msg\_buff}\/ parameter of \verb"evnt_multi" gives  the
address  of a 16 byte buffer to receive an AES message.   As noted
above,  I have discussed standard AES messages elsewhere. The last
column  also mentioned that messages may be used to  simulate  co-
routines  within  a single GEM program.

     A  further possibility which bears examination is the use  of
messages  to coordinate the activities of multiple  programs.   In
single-tasking  GEM,  at least one of these programs would have to
be  a  desk accessory.   In any such use of the GEM messages,  you
should pay careful attention to the possibility of overloading the
queue.   Only  eight  slots are provided per task,  and  messages,
unlike events, cannot be merged by the AES.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Timer}

   The  timer event gives you a way of pacing action on
the  screen,  clocking out messages,  or providing a time-out exit
for   an  operation.   \verb"Evnt_multi"  has  two  16-bit  timer  input
parameters,  {\tt time\_hi}\/  and  {\tt time\_lo}\/,  which are the top and  bottom
halves,  respectively,  of  a  32-bit millisecond count.   However,
this documented time resolution must be taken with a grain of salt
on the ST, considering that its internal clock frequency is 200Hz!

     The  timer  event is also extremely useful  for  polling  the
event  queue.   A  "poll"  tests the queue  for  completed  events
without going into a wait state if none are present.  In GEM, this
is   done  by  generating  a  null  event  which   always   occurs
immediately.  A timer count of zero will do just that.

     Therefore,  you  can poll for any set of events by specifying
them  in  the \verb"evnt_multi" parameters.   A zero timer wait  is  then
added to ensure immediate completion.   Upon return,  if any event
bit(s) {\em other}\/ than \verb"MU_TIMER" are set,  a significant event was found
on the queue.  If only \verb"MU_TIMER" is set, the poll failed to find an
event.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Keyboard}

   There  are  no input parameters for the  keyboard
event.   The  character  which  is read is returned  as  a  16-bit
quantity through the {\tt \&char} parameter.  For historical reasons, the
codes  which  are returned are compatible with the IBM  PC's  BIOS
level scan codes.  You can find this character table in Appendix D
of  the  GEM VDI manual.   In general,  the high byte need only be
considered  if  the lower byte is zero.   If the low byte is  non-
zero, it is a valid ASCII character.

     \verb"evnt_multi"  also returns the status of several modifier  keys
through  the {\tt \&kbd} parameter.   This word contains four significant
bits as follows:

\vskip.5cm
\begin{center}
\begin{tabular}{c|l}
        0x0001 & Right hand shift key\\
        0x0002 & Left hand shift key\\
        0x0004 & Control key\\
        0x0008 & ALT key\\
\end{tabular}
\end{center}
\vskip.5cm

If  a  bit  is  one,  the key was depressed  when  the  event  was
generated.   Otherwise,  the key was up.  Since the state of these
keys  is already taken into account in generating the  {\tt \&char}\/  scan
code,  the  {\tt \&kbd}\/ word is most useful when creating enhanced  mouse
functions, such as shift-click or control-drag.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Random notes on events}

   Although the {\tt \&mx},  {\tt \&my},  {\tt \&btn},  and
{\tt \&kbd}\/ returns are nominally associated with particular event types,
they are valid on any return from \verb"evnt_multi", and reflect the last
event  which was merged into that return by the AES.  If you  want
more  current values,  you may use \verb"graf_mkstate" to resample  them.
Whichever method you choose, be consistent within the application,
since  the point of sampling has an effect on mouse  and  keyboard
timing.

     Although  this and preceding chapters have been  presented  in
terms of a GEM application,  the event system has many interesting
implications  for desk accessories.   Since the AES scheduler uses
non-preemptive  dispatching,  accessories  have an event  priority
effectively  equal  to  the main  application.   Though  "typical"
accessories  wait  only for \verb"AC_OPEN" or \verb"AC_CLOSE" messages  when  in
their  quiescent state,  this is not a requirement of the  system.
Timer  and  other events may also be requested  by  an  accessory.
(Indeed,  there  is  no  absolute requirement  that  an  accessory
advertise  its presence with a \verb"menu_register" call.)  The  aspiring
GEM hacker might consider how these facts could be used to  create
accessories  similar  to  "BUGS" on the Mac,  or  to  the  "Crabs"
program  described  in  the September,  1985 issue  of  Scientific
American.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsubsection{Events and GEM Program Structure}

 Although the  \verb"evnt_multi"
call  might seem to be a small part of the entire GEM system,  its
usage has deep implications for the structure of any  application.
It is generally true that each use of \verb"evnt_multi" corresponds to  a
mode  in  the  program.   For instance,  \verb"form_do" contains its  own
\verb"evnt_multi",  and its invocation creates a moded dialog.  While the
dialog  is in progress,  other features such as windows and  menus
are unusable.  The \verb"graf_dragbox", \verb"graf_rubberbox", and \verb"graf_slidebox"
routines also contain \verb"evnt_multi" calls.   They create a mode which
is sometimes called "spring-loaded",  since the mode vanishes when
some continuing condition (a depressed mouse button) is removed.

     In consequence,  a well-designed,  non-modal GEM program will
contain only one explicit \verb"evnt_multi" call.  This call is part of a
top-level  loop  which  decodes events as they  are  received  and
dispatches  control  to  the appropriate  handling  routine.   The
dispatcher  must  always  distinguish  between  event  types.   In
programs  where  multiple windows are used,  it may also  need  to
determine which local data structure is associated with the active
window.

     This  construction  is  sometimes  called  a  "push"  program
structure,  because  it  allows the user to drive the  application
by generating events in any order.  This contrasts with the "pull"
structure of traditional command line or menu programs,  where the
application is in control and demands input at each step before it
proceeds.    "Push"  structure  promotes  consistent  use  of  the
user interface and a feeling of control on the part of the user.


\newpage

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\section{A new Form Manager}

     This  is  the first chapter
devoted to explaining a large piece of code.  This article is also
the  second  in a series of three concerning  GEM  user  interface
techniques.   The  code is an alternate form (dialog) manager  for
GEM.   It  is listed as {\tt GEMCL13.C}.

     What  is  unique  about this version  of  the  form  manager?
First,  it  implements  all of the functions of the  standard  GEM
\verb"form_do"  routine,  as  well as adding a "hot spots" feature  which
causes  selectable  objects to become mouse-sensitive,  just  like
the   entries  in  menu  dropdowns.    The  second  (and  obvious)
difference  is that this form manager is provided in  source  code
form.   This  gives you the freedom to examine it and change it to
suit your own needs.

     I  have  several  purposes in presenting this  code.   It  is
intended   as  an  example  of  GEM  program  structure,   and  an
application  of  some  of  the  techniques  presented  in  earlier
columns.   It is also relevant to the continuing thread discussing
the necessity of feedback when constructing a user interface.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{On  with  the show}

   Taking your listing in hand,  you  will
quickly notice two things.   First, this program uses the infamous
portability macros,  so that it may be used with Intel versions of
GEM.  Second, the routines are arranged "bottom up", with the main
at the end,  and subroutines going toward the beginning.  (This is
a carry-over from my days with ALGOL and PASCAL.)  You should  now
turn to the \verb"form_do" entry point near the end of the code.

     One change has been made in the standard calling sequence for
\verb"form_do".   The  starting  edit field is now a pointer to a  value,
rather  than  the value itself.   The new \verb"form_do"  overwrites  the
initial value with the number of the object being edited when  the
dialog  terminated.   Using  this  information,  your program  can
restore the situation when the dialog is next called.   As before,
if there is NO editable field, the initial value should be zero.

     There are several local variables which maintain vital  state
information during the dialog interaction.  \verb"Edit_obj" is the number
of  the editable object currently receiving keystrokes.   \verb"Next_obj"
is  set when the mouse is clicked over an object.   If the  object
happens to be editable,  \verb"next_obj" becomes the new \verb"edit_obj".

     Three  variables are associated with the "hot-spot"  feature.
If \verb"hot_mode" is set to \verb"M1_ENTER", then the mouse is outside the area
of the dialog.   If it equals \verb"M1_EXIT", then the mouse is currently
in the dialog.   If it is in the dialog, \verb"hot_obj" indicates whether
there is an active "hot" object.   If its value is NIL (-1),  then
there is no active object.   Otherwise,  it is equal to the number
of the object which is currently "hot",  that is,  inverted on the
screen.   Finally, \verb"hot_rect" is the current wait rectangle.  If the
mouse is outside of the window, then the wait rectangle equals the
dialog's  ROOT.   If there is a current hot object,  then \verb"hot_rect"
equals  that  object's screen rectangle.   If the mouse is in  the
dialog,  but  not  within  a hot object,  then the wait  rectangle
defines  the  area within which no further  collision  checks  are
necessary.   This  is  arrived at through an  algorithm  explained
below.

     \verb"Form_do's" initialization code sets up the hot-spot  variables
to  trigger  if  the mouse is within the  dialog.   It  also  sets
starting  values  for \verb"edit_obj" and \verb"next_obj" which will  cause  the
edit startup code to be activated.

     The main portion of \verb"form_do" is a loop, exhibiting the type of
event  driven  structure  discussed in the  last  column.   Before
entering the \verb"evnt_multi" wait,  the status of \verb"next_obj" and \verb"edit_obj"
are  checked  to  see if a new object should  be  initialized  for
editing.   If  so,  \verb"objc_edit"  is called with the \verb"EDINIT"  function
code.   NOTE:  the \verb"objc_edit" calling sequence used in this program
differs from the one given in the AES manual,  which is incorrect!
You  should check the bindings you are using to be sure they  will
work with this code, and modify as necessary.

     The \verb"evnt_multi" is set up to wait for a mouse click (single or
double),  for  a  keyboard  input,  or  for the mouse  to  make  a
"significant"  movement,  as  discussed above.   Notice that since
\verb"form_do" is used as a subroutine, it does not handle messages which
are  normally  processed  by the main loop  of  your  application.
Notice that this creates a mode,  and that this routine as written
handles modal dialogs.   You could,  however, use this code as the
basis for a non-modal dialog handler by drawing the dialog  within
a  window,  and  combining the main loop of \verb"form_do" with the  main
loop  of your application.   (This possibility may be examined  in
the future.   In the meantime,  it is left as an exercise for
the reader.)

     The  event  bit vector is returned to the  variable  "which".
Since events are not mutually exclusive,  each possible event type
must be examined in turn before returning to the \verb"evnt_multi"  call.
The form manager's event handling routines are \verb"form_hot", for mouse
rectangle event, \verb"form_keybd", for character input, and \verb"form_button",
for  mouse  clicks.   \verb"Form_keybd"  and \verb"form_button" are  allowed  to
terminate  the  dialog by returning a value of false to  the  loop
control variable "cont".   If termination is imminent, or the user
has  clicked  on a new editable object,  \verb"objc_edit" is called  with
\verb"EDEND"  to remove the cursor from the old object.   The normal flow
of control then returns to edit setup and \verb"evnt_multi".

     A few cleanup actions are performed upon termination.  If the
terminating  object  (stored in \verb"next_obj") is not the same  as  the
\verb"hot_obj", then a race condition has occured and the hot object must
be cleared with \verb"objc_toggle" before exiting.   After this test, the
final  \verb"edit_obj"  value is passed back via the parameter,  and  the
terminating object is returned as the function value.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Relaxen und Watchen das Blinkenlichten}

\verb"form_hot" is
responsible  for  maintaining on-screen hot-spots,  and  correctly
updating  the  internal hot-spot variables.   It is about  halfway
through the listing.

     The first action in \verb"form_hot" is to determine if the mouse has
just exited an object which is hot.  In this case, \verb"objc_toggle" is
called to unhighlight the object and reset the \verb"SELECTED" flag.

     The current mouse position is passed to \verb"form_hot" by  \verb"form_do".
It  is checked against the root rectangle of the dialog to see  if
the mouse is inside the dialog.  If not, the program must wait for
it  to re-enter,  so \verb"form_hot" sets the rectangle and waiting  mode
accordingly, and returns NIL as the new \verb"hot_obj".

     When the mouse is within the dialog, a regular \verb"objc_find" call
determines  the object at which it is pointing.   For an object to
be  mouse-sensitive,  it must be \verb"SELECTABLE" and not \verb"DISABLED".   If
the  found object meets these tests,  the mouse will "hover"  over
the  object,  waiting  to leave its screen rectangle.   Since  the
object might already be \verb"SELECTED" (and hence drawn reversed),  this
is checked before \verb"objc_toggle" is called to do the highlighting and
selection  of  the  object,  which becomes the \verb"hot_obj".   (If  the
object was already \verb"SELECTED", the \verb"hot_obj" becomes NIL.)

     The  toughest  condition  is when the  mouse  is  within  the
dialog,  but  not over a mouse-sensitive object.   The regular GEM
event  structure  will not work,  because it can only wait on  two
rectangles,  and  there  may be many more selectable objects in  a
dialog  tree.   I have found a way around this limitation using  a
combination of the \verb"map_tree" utility
with the principle of visual hierarchy in object trees.

     In  summary,  the  algorithm  attempts to  find  the  largest
bounding rectangle around the current mouse position, within which
there are no mouse-sensitive objects.   It starts with a rectangle
equal  to the dialog root,  and successively "breaks" it with  the
rectangle of each mouse-sensitive object.  The next few paragraphs
examine this method in detail.

     Since  C  lacks  the  dynamic scoping  of  LISP,  from  which
\verb"map_tree" was derived, it is necessary to set up some globals to be
used during the rectangle break process.   \verb"Br_rect" is the \verb"GRECT" of
the current bounding rectangle.   \verb"Br_mx" and \verb"br_my" hold the current
mouse position.   \verb"Br_togl" is a switch which determines whether the
next  break will be attempted horizontally or  vertically.   After
initializing these variables, \verb"form_hot" uses \verb"map_tree" to invoke the
\verb"break_obj" routine for every object in the dialog.

     \verb"Break_obj"  first intersects the rectangle of the object  with
the  current  bounding  rectangle.   If they  are  disjoint,  then
neither  the object nor any of its offspring can  possible  affect
the  operation,  so FALSE is returned,  causing \verb"map_tree" to ignore
the subtree.

     The  object is next checked to see if it is  mouse-sensitive.
As before, it must be \verb"SELECTABLE" and not \verb"DISABLED", and it must not
be  hidden (this was checked automatically by  \verb"objc_find"  before).
If  these  conditions are met,  then the object intrudes into  the
current  bounding rectangle.   To maintain the desired  condition,
part of the rectangle must be removed or "broken away".

     In  many  cases,  the  break  operation can  be  done  either
horizontally or vertically.  Since we have no prior information as
to which way the mouse will move next,  \verb"break_obj" uses the \verb"br_togl"
flag to alternate which direction it will try first.   This should
yield the most nearly square rectangle.

     The  \verb"break_x" and \verb"break_y" routines are very similar.   In each
case,  the  segment occupied by the breaking object is compared to
the  point  occupied  by the mouse.   If the point is  within  the
segment,  there is no possible break in this dimension,  and FALSE
is  returned.   If  the point lies outside the segment,  then  the
rectangle  may be successfully broken by reducing this  dimension.
This is done, and TRUE is returned to report success.

     The \verb"break_y" routine also employs a look-ahead test to prevent
a possible infinite loop.   It is conceivable,  though not likely,
that someone might nest a non-\verb"SELECTABLE" object completely  within
another  \verb"SELECTABLE" object(s).   If the mouse point is within such
an  object,  the  algorithm  will not be able to  select  a  break
dimension.   In the current version, the mouse rectangle is simply
forced  to  a single pixel for this case.   (Note that is  is  NOT
sufficent to simply wait on the non-selectable object's rectangle,
since  other \verb"SELECTABLE" objects may overlap it and follow  it  in
tree order.)

     Since \verb"map_tree" examines all possible objects, \verb"br_rect" will be
the  correct bounding rectangle at completion.   Note that you can
readily  adapt this technique to other uses,  such as hot-spotting
while  dragging  objects.   It  is  much  less  demanding  of  CPU
resources than other methods, such as repetitive \verb"objc_finds".

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{What a character!}

  The \verb"form_keybd" routine acts as a filter on
character  input.   When  it  recognizes a control  character,  it
processes it and zeroes the keyboard word.  Other chararacters are
passed on to \verb"objc_edit" to be inserted in \verb"edit_obj".  If there is no
editing object, the character goes to the bit bucket.

     The   \verb"form_keybd"   given   implements   the   standard    GEM
functionality with two minor additions.   First, a carriage return
in  a dialog with no \verb"DEFAULT" exit object is taken as a tab.   This
allows  <CR> to be used "naturally" in dialogs with several  lines
of text input.   Second,  tabs and backtabs "wrap around" from top
to  bottom  of  the dialog,  and are done by "walking  the  tree",
rather  than relying on the \verb"LASTOB" flag to signal the end  of  the
dialog.   This  allows the new form manager to handle dialog trees
which are not contiguous in memory.

     The  code sets up several global variables for use by  mapped
functions.   \verb"fn_obj" is the output from both \verb"find_tab" and
\verb"find_def". \verb"fn_dir" is an input to \verb"find_tab". 
\verb"Fn_last", \verb"fn_prev", and \verb"fn_last" are used while
searching for tab characters.

     A  carriage  return results in a search of the  entire  tree,
using  \verb"map_tree" and \verb"find_def",  for an object with its
\verb"DEFAULT" flag set.  Its \verb"SELECTED" flag is set and it is
inverted on the screen to indicate  the action taken.  
\verb"Form_keybd" returns a FALSE to  force termination  of  the main
\verb"form_do" loop.   If no \verb"DEFAULT" is  found, control passes
to the tab code.

     The  tabbing  procedure is somewhat complicated  because  the
same code is used for forward and backward tabbing.  The old value
of \verb"edit_obj" (the object being tabbed FROM) is placed into
\verb"fn_last". \verb"fn_dir"  is set to one for a forward tab, and
zero for a  backward tab.

     The general strategy is to scan the entire tree for  \verb"EDITABLE"
objects,  always  saving  the  last one found  in  \verb"fn_prev".   When
tabbing  forward  \verb"fn_last"  is checked against  \verb"fn_prev".  
A  match indicates  that  the  current object is  the  one  desired.   When
tabbing  backward the current object is checked  against  \verb"fn_last".
If  they  match,  \verb"fn_prev" is the desired object.   This  procedure
requires two passes when the tab "wraps around" the tree, that is,
when  the  desired object as at the opposite end of  the  traverse
from the old editing object.

     The  result  of  the  tab  operation  is  written  back  into
\verb"form_do's"  \verb"next_obj" parameter,  and becomes the new editing
object at the beginning of the next loop.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Button down}

  The \verb"form_button" procedure is lengthy because it
must  recognize  and  handle  mouse clicks  on  several  types  of
objects:  \verb"EDITABLE",  \verb"SELECTABLE", and \verb"TOUCHEXIT".  The first section
of code rejects other objects, which cannot accept a click.

     The  next  piece of \verb"form_button" makes a special check  for  a
double click on a \verb"TOUCHEXIT" object.   This will cause the high bit
of the returned object number to be set.   (By the way,  this also
occurs  in  the standard \verb"form_do".)  This flag allows  user  dialog
code to perform special processing on the object.

     The largest piece of \verb"form_button" handles the various cases in
which the \verb"SELECTABLE" flag may be set.   Setting the \verb"RBUTTON" (radio
button) flag causes all of the object's siblings in the tree to be
deselected  at  the  time the object  is  clicked.   The  \verb"do_radio"
routine uses the \verb"get_parent" utility to find the ancestor, and then
performs the deselect/select operation.

     If the \verb"SELECTABLE" object is not \verb"TOUCHEXIT", then \verb"graf_watchbox"
is used to make sure that the mouse button comes back up while  it
is within the object.  Otherwise, the click is cancelled.  Care is
necessary  here,  since the hot-spot code may have already set the
\verb"SELECTED" flag for the object.   (We cannot be sure of this,  for a
race condition may have occurred!)

     If  the \verb"SELECTABLE" object is \verb"TOUCHEXIT",  then the application
has requested that \verb"form_do" exit without waiting for the button  to
go back up.   In both this and regular \verb"form_do",  \verb"TOUCHEXIT" objects
are  used when you want to provide immediate response  (animation)
within the context of a dialog.

     The  final parts of \verb"form_button" do cleanup.   If the  clicked
object  was  already hot-spotted,  \verb"hot_obj" must be reset  to  NIL,
otherwise  \verb"form_do"  will carefully unselect the object  which  has
just been selected!

     If  the  \verb"EXIT" or \verb"TOUCHEXIT" flags are  in  force,  \verb"form_button"
returns  FALSE to force the completion of \verb"form_do".   For  \verb"EDITABLE"
objects,  \verb"next_obj"  is left intact to replace \verb"edit_obj" during  the
next  loop.   Otherwise,  \verb"next_obj" has done its job and is zeroed,
and \verb"form_button" returns TRUE for continuation.

     This  concludes the tour of the alternate \verb"form_do".   The best
cure for any confusion in this explanation is to compile the  code
into  an  application  and  watch  how  it  runs  with   different
resources,  or attack it with a debugger.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\subsection{Operators are standing by}

  I encourage you to modify  this
code  to meet your particular needs and incorporate it  into  your
application.   I  would  like to request than anyone who comes  up
with  significant improvements (or bug fixes) send them to  me  so
they  can  be made generally available.   You can do this via  the
ANTIC ONLINE Feedback, or by sending E-mail to 76703,202.
\newpage


% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\newpage
\section{Coping With GEMDOS}

While it's fun playing with windows and object trees, one of the day-to-
day realities of working with the ST is its operating system, GEMDOS. A 
successful application should insulate the user from the foibles and 
occasional calamities of the machine's file system. The GEM environment 
provides some minimal tools for doing this, but a good deal of 
responsibility still rests with you, the programmer.

This chapter tries to address the GEM/DOS 
integration problem by providing you some stock code for common 
functions, along with a discussion of some of the worst "gotchas" 
lurking for the unwary. The source for this column is called {\tt GEMCL15.C}.


\subsection{Another bit of history}

There has been a good deal of confusion in the Atari press and among 
developers over what GEMDOS is, and how it relates to TOS and CP/M-68K. 
It's important to clear this up, so you can get a true picture of what 
GEMDOS is intended to do. The best way is to tell the story of GEMDOS' 
origins, which I can do, because I was there.

As most developers are aware, GEM was first implemented on the IBM PC. 
PC GEM performed two functions. The first was a windowed graphics 
extension to the PC environment. The second was a visual shell, the 
Desktop, which ran on top of the existing operating system, PC-DOS.

When work started on moving GEM to the ST, there were two big problems. 
First, no STs actually existed. Second, there was no operating system on 
the 68000 with which GEM and the Desktop could run. Unix was too large, 
and CP/M-68K lacked a number of capabilities, such as hierarchical 
files, which were needed to support GEM.

Work on porting the graphics parts of GEM to the 68000 had to start 
immediately to meet schedules. Therefore, CP/M-68K running on Apple 
Lisa's was used to get this part of the project off the ground. 
Naturally, the Alcyon C compiler and other tools which were native to 
this environment were used.

In parallel, an effort was begun to write a new operating system for the 
68000, which would ultimately become the ST's file system. It was 
designed to be a close clone of PC-DOS, since it would perform the same 
functions for GEM in the new environment. At this point, the term TOS 
was introduced. TOS really meant "the operating system, whatever it may 
be, that will run on the ST", since not even the specifications, let 
alone the code, were complete at that time.

The first engineer to work on "TOS" at Digital Research was Jason 
Loveman. This name leaked to the press, and in some distorted fashion 
generated a rumor about "Jason DOS", which was still just the same 
unfinished project. As "TOS" became more solid, the developer's tools 
were ported to the new environment one by one, and the GEM programming 
moved with them. CP/M-68K was completely abandoned, though the old 
manuals for C and the tools lived on and are still found in the Atari 
developer's kit.

All of this work had been done on Lisas or Compupro systems fitted with 
68000 boards. At this point, workable ST prototypes became available. An 
implementation of "TOS" for the target machine was begun, even before 
the basic operating system was fully completed.

The other intent for the new operating system was to be a base for GEM 
on other 68000 systems as well as the ST. Because of this, Digital 
Research named it GEMDOS when it was finally complete, thus providing 
the final bit of nomenclature. "TOS" as now found in the ST is in fact a 
particular implementation of generic GEMDOS, including the ST specific 
BIOS.

So, GEMDOS is a PC-DOS clone, but, not quite. There are enough 
differences to cause problems if they are ignored. (Remember, it looks 
like a duck, and quacks like a duck, but it's not a duck.)


\subsection{Going for it}

As a first example, consider the routines {\tt open\_file()} and {\tt create\_file()} 
at the beginning of the listing. They make use of the GEMDOS calls 
\verb"Fopen()" and \verb"Fcreate()". You will notice that these names are not the ones 
specified in the Digital Research GEMDOS manual. Developers who have 
used PC GEM will also observe that they are radically different from the 
function names in the PC-DOS bindings.

In fact, all of the GEMDOS function calls on the ST are defined as 
macros in the file osbind.h, distributed with the developer's kit. At 
compile time they are turned into calls to the assembly language routine 
{\tt gemdos()}, part of the osbind.o binary. So, if you find the naming 
conventions to be particularly offensive for some reason, just edit the 
appropriate macros in osbind.h.

In DRI's PC-DOS bindings, any error codes were returned in the global 
variable \verb"DOS_ERR". In the GEMDOS bindings, the operation result or an 
error code is returned as the value of the calling function. In the case 
of \verb"Fopen()" and \verb"Fcreate()", the result is a valid file handle if it is 
positive. A negative result is always an error code, indicating that the 
operation failed.

An application which encounters a GEMDOS error should display an alert, 
and query for retry or abort. The type of loop structure exemplified by 
{\tt open\_file()} and {\tt create\_file()} should be usable with most GEMDOS 
functions which might fail. The AES provides a function, \verb"form_error", 
which implements a set of "canned" error alerts appropriate to the 
various possible errors.

However, this is where the fun starts. For unknown reasons, the 
\verb"form_error" on the ST expects to see PC-DOS, not GEMDOS, error codes as 
it's input! Therefore you need a routine to translate one into the 
other. The routine {\tt dos\_error()} in the listigs provides this function. 
The GEMDOS errors are in the same sequence as those for PC-DOS, but 
their numerical order is reversed and shifted. Notice also that 
{\tt dos\_error()} does NOT perform the translation if the error code is less 
than -50. These codes have no PC-DOS equivalent; computing a bogus 
translation will cause \verb"form_error" to crash. Instead, they are passed 
through verbatim, resulting in a "generic" alert which gives only the 
error number.

The other major task in integrating a GEM application with the file 
system is selecting file names for input and output. Again, the AES 
provides some assistance with the \verb"fsel_input" call, which invokes the 
standard file selector dialog.

There are several drawbacks to the standard file selector. One is that 
the "ITEM SELECTOR" title is constant and cannot be changed by the 
application. This could cause confusion for the user, since it may not 
be clear which of several functions, closely spaced in the FILE menu, 
was actually invoked. While it might be possible to find and "rewire" 
the AES resource that defines the file selector, it is unlikely that 
such an approach would be portable to a later version of ST GEM.

A viable approach to eliminating confusion is to display a small 
"marquee" box, with a message defining the operation, on the screen just 
above the file selector. To do this, you must initialize the location of 
the box so that it is outside of the file selector's bounds, and then 
draw it just before invoking the file selector. This way they will 
appear together. Before returning to its main event loop, the 
application should post a redraw message for the "marquee" area. The AES 
will merge this redraw with the one generated by \verb"fsel_input", and the 
result will be received by the application's \verb"evnt_multi".

Later versions (since TOS 1.4) of the ST GEM provide the \verb"fsel_exinput"
call that allows the programmer to specify a title line. But since this
call is not available on older machines we have to check which version
of TOS is installed, and may have to call the old routine after all.

Another problem with the file selector is that it resets your 
application's virtual workstation clip rectangle without warning. There 
are other AES functions, such as \verb"objc_draw", which also do this, but the 
file selector can be troublesome because it may be the only AES call 
used by some VDI-based ST applications.

The veteran developer will also notice that the file selector takes and 
returns the path and filename as two separate strings, while the GEMDOS 
file functions require a fully pathed file name. Also, the file selector 
doesn't remember its "home" directory; you are responsible for 
determining the default directory, and keeping track of any changes. The 
remainder of the listing and chapter is devoted to set of utilities 
which should alleviate some of the "grunt work" of these chores.

The top level routine in this collection is {\tt get\_file()}. It is called 
with two string arguments. The first must point to a four byte string 
area containing the desired file name extension (three characters plus a 
null). The second is the default file name.

If the default file name is non-null, then {\tt get\_file()} invokes 
{\tt parse\_fname()} to break it into path and name. {\tt Parse\_fname()} also adds 
the necessary "wild card" file specification to the path, using the 
extent name given as input.

If no default file was supplied, or the default did not contain a path, 
the routine {\tt get\_path()} is invoked to find the current default directory 
and construct a legal path string for it.

The results of these manipulations are supplied to \verb"fsel_input". Notice 
that the result of the file selector is returned via its third argument, 
rather than as a function value. If the result is TRUE, {\tt get\_file()} 
merges the temporary path and file string, storing the result via the 
second input parameter. This result string is suitable for use with 
Fopen, and may be resubmitted to {\tt get\_file()} when the next operation is 
invoked by the user.

{\tt Parse\_fname()} is straight-forward C. It looks backward along the file to 
find the first character which is part of the path. The tail of the 
filename is copied off, and its former location is overlaid with the 
wild card specification.

{\tt Get\_path()} is a bit more interesting. It makes use of two GEMDOS 
functions, \verb"Dgetdrv()" and \verb"Dgetpath()" to obtain the default disk drive and 
directory, respectively. Note that \verb"Dgetpath()" will return a null string 
if the current default is the root, but it puts a back-slash at the 
beginning of the path otherwise. This forces a check for insertion in 
the root case, since the file selector wants to see something like 
\verb"A:\*.RSC", rather than \verb"A:*.RSC". After making this fix, {\tt get\_path()}
concatenates the wild card specification derived from the input extent.

The last routine in the listing is {\tt new\_ext()}. This utility is useful if 
your application uses more than one associated file at a time. For 
instance, the Resource Construction Set uses both an RSC and a DEF file, 
with the same base name. {\tt New\_ext()} takes a fully formed file name, and 
replaces its old extent with the new one which you supply. This lets you 
quickly generate both file names after one call to the file selector. 
Notice that {\tt new\_ext()} looks BACKWARD along the name to find the 
delimiting period, since this character can also be part of a 
subdirectory name in the path.

So we reach the end of the code and this chapter. Hopefully both will 
keep you profitably occupied for a while. The next chapter will return to 
graphics topics, with a look at writing customized rubber box and drag 
box routines.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\newpage
\section{Interface Potpourri}

This chapter of ST PRO GEM presents code 
implementing several user interface techniques: progress indicators, 
rubber boxes, and draggable boxes with mouse sensitive targets. The code 
also includes some utility routines for handling resources, event calls, 
and VDI line drawing.

There are several files for this column. Note the plural - in addition 
to the usual C sources stored in {\tt GEMCL16.C}, the files {\tt GEMCL16.RSC}, 
{\tt GEMCL16.DFN}, {\tt GEMCL16.H}, and {\tt GEMCL16.RSH} are a template resource for 
building progress boxes. {\tt GEMCL16.RSC} is the resource binary, and 
{\tt GEMCL16.H} is its symbol binding file, to be used with {\tt GEMCL16.C}. The RSH 
file is a C image of the resource - you would need {\tt STCREATE} to 
regenerate it.

{\tt GEMCL16.DFN} is the binary symbol file for the resource. It is in the 
format used by the NEW ST Resource Construction Set. This fixes a number 
of bugs, and has a much faster user interface.


\subsection{Making Progess}

The need for feedback in interface designs has been discussed in 
previous chapters. One instance which is often necessary is the so-called 
progress indicator. A progress indicator is used when your application 
is doing a long operation. It shows that the function is continuing 
satisfactorily, and is not hung in a loop. When possible, it also gives 
an indication of the fraction of the operation which has been completed. 
The thermometer bars on the Desktop format and copy operations are 
examples.

The sample code shows two types of progress indicator. Both are built 
within the structure of a dialog resource. The first type uses a 
variable line of text to describe each phase of an operation as it 
occurs. The rewriting of the text provides action on the screen; the 
fact that it is different each time gives reassurance that the program 
is not hung. The second type of indicator is the thermometer bar. This 
is more useful when the operation is uniform, allowing you to estimate 
the fraction completed. Let's look at the code.

The routines {\tt beg\_prog()} and {\tt end\_prog()} are common to the two types. The 
code is very similar to the standard dialog handling procedure, but is 
broken into two parts. {\tt Beg\_prog()} assumes that the progress indicator 
box is defined by a dialog tree named {\tt PROGRESS}. Such a tree is provided 
in {\tt GEMCL16.RSC}. Beg\_prog() makes the usual calls to center and draw the 
box. The rectangle computed in the centering operation is stored via a 
\verb"GRECT" pointer passed in the parameter. This rectangle compensates for 
the outline around the box, and must be supplied to {\tt end\_prog()} when the 
operation is complete.

The first version of {\tt set\_prog()} in the code implements the changing 
text progress indicator. It looks in a tree labelled \verb"STRINGS" for the 
object number which is passed as a parameter. It is assumed that this 
object is a \verb"G_STRING". The address of the new text is loaded from the 
object's \verb"ob_spec" field. (For those with the new RCS, it would be easy to 
alter this routine to use free strings. Simply replace the first two 
lines with: \verb"rsrc_gaddr(R_STRING, strno, &saddr);" and supply parameters 
which are the names of strings in a \verb"FRSTR" box.)

Once the new text is found, the {\tt set\_text()} utility is called to update 
the \verb"TEDINFO" attached to object \verb"PLINE" in the \verb"PROGRESS" tree. {\tt Set\_text()} 
will insert the new text address in \verb"te_ptext", and the new text length in 
\verb"te_txtlen". {\tt Disp\_obj()} is then used to redraw only the rectangle 
belonging to \verb"PLINE".

\verb"PLINE" must be defined as a \verb"G_BOXTEXT" object with a solid white 
background, and with the \verb"CENTERED" attribute set. It must extend entirely 
across the progress box. This guarantees that the previous text will be 
covered over, and the new text will be centered in the box.

The second version of {\tt set\_prog()} implements the thermometer bar progress 
indicator. The \verb"PROGRESS" tree also includes an object \verb"PROBOX" which 
defines the outline of the thermometer. It is a \verb"G_BOX" object with a 
solid white background, and a one-outside border. The object \verb"PROBAR" is 
nested inside it, with the left edges matching. \verb"PROBAR" is also a \verb"G_BOX", 
with a solid red background and a one-outside border as well. {\tt Set\_prog()} 
creates the thermometer effect by growing and redrawing \verb"PROBAR".

{\tt Set\_prog()} requires two parameters. Maxc is an estimate of the total 
duration of the operation, in arbitrary units. Value is the (new) amount 
completed, in the same units. {\tt Set\_prog} performs two operations. First, 
it computes the fraction value/maxc, and sets \verb"PROBAR" to that fraction of 
the width of \verb"PROBOX". Second, it computes the rectangle which is the 
difference between the old and new widths of \verb"PROBAR", and redraws only 
that part of the progress box. This prevents an annoying flash on the 
screen when the indicator is updated.

These two types of progress indicators have been presented in separate 
routines for convenience in explanation. You can easily combine them in 
a single procedure to create an indicator with both effects.

The final progress indicator routine is called {\tt esc\_prog()}. During many 
lengthy operations is desirable to provide an abort option to the user. 
{\tt Esc\_prog()} lets you do this by polling the keyboard for an escape (ESC)
character. A zero timer value is used to guarantee an immediate return 
if no character is found. Characters other than escape are ignored.

{\tt Esc\_prog()} returns \verb"TRUE" if an abort is requested, and \verb"FALSE" if the 
operation is to continue. In your application, you can either pair calls 
to {\tt set\_prog()} and {\tt esc\_prog()}, or recode {\tt set\_prog()} to automatically make 
the abort check. In any case, you should add an information line to the 
progress box, telling the user how the operation may be halted.

Of course, this type of progress indicator is not the only option 
available on the ST. Other ideas such as changing window titles, or 
displaying a succession of differing icons are equally valid. Sometimes 
the nature of your application may suggest an alternate metaphor. For 
instance, the progress of recalculating a spreadsheet might be indicated 
by darkening successive columns in a miniature image of the sheet. 
Occasionally, the computing operation is visual itself, and will not 
require an explicit indicator. An example is redisplaying objects in a 
2D or 3D drawing program.


\subsection{Boxed in}

The second part of the listing implements two types of user interaction 
using the mouse. The first creates a "rubber box" on the screen, that 
is, a box whose size is controlled by moving the mouse. This is similar 
to the AES \verb"graf_rubberbox" call, but allows the box to move in any 
direction from its origin, while the GEM function only allows movement 
to the lower right. The AES \verb"graf_rubberbox" call does allow movement
in any direction however if the maximum values for the box are NEGATIVE.
The resulting rectangle may have to be corrected if the upper left corner
has changed.

The second technique allows the user to drag the outline of a box around 
the screen using the mouse. Again, this is similar to the AES 
\verb"graf_dragbox" call, but this version is augmented with code which 
"hotspots" selectable objects when the mouse and object pass over them. 
These routines are another illustration of the usage of the \verb"evnt_multi" 
function, and its combination with VDI drawing to create new interaction 
techniques.

The "rubber box" subroutine is called {\tt fourway\_box()}. Its parameters are 
the current VDI handle (NOT a window handle!), and two \verb"GRECT" pointers. 
The first \verb"GRECT" must have its \verb"g_x" and \verb"g_y" initialized with the fixed 
point of the rubber box. The second GRECT contains an outer bound box 
for the stretching action.

{\tt Fourway\_box()} begins by setting the VDI drawing mode and color. The 
exclusive or, black combination guarantees that redrawing a figure twice 
in the same location will exactly erase it. Next, the routine asserts 
the mouse control flag. This stops the window manager from tracking the 
mouse, with the effect that menus will not drop down during the 
operation.

The fixed coordinates are saved in the variables {\tt ox} and {\tt oy}, and an 
initial mouse reading is obtained with \verb"graf_mkstate". At this point, the 
event loop is entered.

At each iteration, the loop finds the upper left most of the fixed 
vertex and the current mouse position, and updates the tracking \verb"GRECT" 
accordingly. A call to the utility {\tt rc\_intersect()} is used to restrict 
the size of the rubber box to the given limiting rectangle. Note that if 
you need a lower limit to the size of the rubber box, it can be achieved 
by adding another \verb"GRECT" pointer "lower" to the parameter list, and using 
the call {\tt rc\_union(lower, rubber);} This works because the union operation 
selects the larger of two rectangles if they are nested.

{\tt Rub\_wait()} will be described in detail below. Its returns are the new 
mouse position, and an indication of the current mouse button state. If 
the button remains down, the loop continues. When the button is 
released, the rubber box terminates, since it is a "spring-loaded" modal 
operation. Before ending, {\tt fourway\_box()} returns mouse control to the 
window manager. The return from the routine is found in the rubber 
\verb"GRECT", and is the final extent of the box.

{\tt Rub\_wait()} is a utility used by both box techniques. Its purpose is to 
do one step of the box animation, and wait for a mouse movement, or the 
release of the button. {\tt Rub\_wait()} preserves the state of the screen.

The first action is to draw an exclusive or'ed dotted line box at the 
given rectangle. Next, {\tt rub\_wait()} calls \verb"evnt_multi" to wait for the mouse 
button to come up, or the mouse to move out of a one pixel rectangle. 
When the event is detected, the same code is used to remove the box. A 
value of \verb"TRUE" is returned if the mouse button is still down; the curious 
logical construction is necessary since BOTH events could occur at once.

A short examination of the {\tt vdi\_xbox()} code is also useful. After 
converting the rectangle to polyline format, the {\tt vdi\_xline()} routine is 
called. {\tt Vdi\_xline} draws a dotted line, but does not use the VDI line 
style attribute. This is avoided because the VDI has problems with 
corner points when drawing styled lines in \verb"XOR" mode. Instead, a 
selection is made from a set of user defined line styles, based on the 
direction of the stroke, and the odd/evenness of the starting horizontal 
pixel. This assures that the figure will be exactly erasable.


\subsection{Hot Stuff?}

The drag box routine is more subtle, because care is needed to correctly 
synchronize the movement of the mouse cursor and the box, and the 
highlighting of target objects. The parameters {\tt vdi\_handle} and {\tt limit} are 
identical to those in {\tt fourway\_box()}. The \verb"GRECT" pointed to by box 
contains the width and height of the movable box when {\tt hot\_dragbox()} is 
entered. On exit it also contains the last x,y coordinates of the box. 
The variable tree is a pointer to the root of a resource tree defining 
the hot spots for the drag operation. Only objects tagged \verb"SELECTABLE" are 
hotspotted. {\tt Hot\_dragbox()} returns the number of such an object if the 
box is "dropped" on it, otherwise a NIL is returned.

Initialization proceeds as above, until the \verb"graf_mkstate" call. Here is 
the first potential synchronization problem. If the user moves the mouse 
very quickly after initiating the drag, it may already be outside the 
box by the time \verb"graf_mkstate" samples the position. The \verb"min/max" 
operations given lock the box onto the cursor, no matter where it has 
strayed. The mouse/box offsets, {\tt ox} and {\tt oy}, will remain constant for the 
rest of the operation.

{\tt Hover\_obj} will contain the number of the object which is currently 
highlighted. It is initialized to \verb"NIL", indicating no object is currently 
marked. {\tt Hot\_dragbox()} now enters a loop with termination conditions 
identical to the rubber box.

The current desired position of the box is computed by subtracting the 
box/mouse offset from the current mouse position. The {\tt rc\_constrain()} 
call ensures that the box will not leave the bounding rectangle. Note 
that {\tt rc\_intersect} would not work here - it would alter the size of the 
draggable box, rather than "nudging" it back into the bounds.

Upon return from {\tt rub\_wait()}, a number of conditions must be checked to 
determine the correct object to highlight, if any. First, we must make 
sure that the mouse is actually within the legal bounds. If not, there 
may be an ambiguous selection, with the mouse over one object and the 
box over another. We choose to do nothing in this case, and set 
{\tt hover\_obj} to \verb"NIL". If the mouse is in bounds, \verb"objc_find" looks for a 
target object. If one exists, it must be \verb"SELECTABLE", or it is forced to 
\verb"NIL".

Next the new object, stored in {\tt ret\_obj}, is compared to the old 
highlighted object, in {\tt hover\_obj}. If they are different, a switch must 
be made. Since either could be \verb"NIL", a check is necessary before calling 
{\tt obj\_toggle} to invert/reinvert the screen image of the object. When the 
loop is complete, the final {\tt hover\_obj} is returned to normal state before 
its number is returned.

You may notice that this method of highlighting objects is different 
from the incremental tree descent and rectangles method presented earlier.
While not as efficient, the \verb"objc_find" technique is simpler to 
code and may be adequate for many uses. If your program will make heavy 
use of the drag box routine, or will have large trees of target objects, 
you may wish to integrate the incremental hotspotting algorithm with 
{\tt hot\_dragbox()}. This would be simple to do; just use \verb"evnt_multi"'s second 
mouse rectangle for the states associated with the hot-spotter. The 
single pixel rectangles would have to remain, in order to maintain the 
animation effects.

\subsection{R2D2, where are you?}

Finally, you may also notice that the so-called portability macros have 
disappeared from the listing. Indeed, they are gone for good. Since the 
beginning of this column, the growth of the ST GEM developer community 
has outstripped that on the PC. It no longer seems appropriate to 
inconvenience ST developers and violate standard C syntax for the sake 
of Intel's design flaws. Those who still need compatibility with the PC 
may achieve it by compiling under Intel large model, or by writing "sed" 
scripts to translate \verb"(tree+obj)->ob_spec" and the like to their macro 
equivalents.

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\newpage
\section{PC/ST Resource Converter}


This chapter of ST PRO GEM is the first to feature a 
complete GEM application. The program converts resource files between 
the ST (68000) and IBM PC (Intel) formats used by the respective 
versions of GEM and the Resource Construction Set.

The Resource Converter will, for the most part, be of direct use only if 
you are doing cross-development of GEM software on these two systems. In 
this case, you will want to read this entire chapter, starting with the 
"What It Does" heading. You may also be interested in an article on 
PC/ST conversion written by Mark Skapinker of Batteries Included, which 
appears in the Fall 1986 issue of START magazine.

If you are not doing cross machine development, you can still get 
something out of this column. Reading the program code and following the 
discussion, you will find practical examples of using GEM dialogs and 
following the internal structure of a resource file. Finally, there is a 
good deal of standard code for GEM initialization, AES utility 
functions, and GEMDOS file handling which you can extract for your own 
uses. If you fall in this category, skip the first parts of the column, 
and resume reading at the "How it Works" heading.

The files and their contents for this chapter are:

\begin{description}

\item[RSCVMAIN.C  ] This is the C source for main routine
\item[RSCVFILE.C  ] This is the C source of GEMDOS utilities    
\item[RSCVLIB.C   ] C source of AES utility functions
\item[RSCONV.PRG  ] Linked binary of converter
\item[RSCONV.RSC  ] Binary resource image (ST format)
\item[RSCONV.DFN  ] Symbol file for resource (ST format for RCS 2.0)
\item[RSCONV.H    ] Object/tree name file for resource
\item[RSCVLINK.SH ] C-shell script for linking RSCONV

\end{description}

The final two files will be of use only if you are using Dave 
Beckemeyer's Micro C-Shell environment. If not, you can simply translate 
them to \verb".BAT" and/or \verb".INP" form for use with the Atari batch program and 
linker.


\subsection{What it does}

A converter program is necessary because of the differing order of 
storage on the 68000 and Intel chips: the order of significance of bytes 
within words is reversed, as well as the order of words within long (32-
bit) quantities. Attempting to load an unconverted resource on a GEM 
system with the other architecture will result in a crash, because all 
of the pointer and integer fields will be incorrect.

In addition, the format of symbol definition (DEF) files differs between 
the PC and ST implementations of the RCS in its first version. In the 
latest version from DRI, the formats do correspond, and the files now 
carry an extent name of DFN. However, the byte swapping problem must be 
corrected in either format for the symbols to be correctly loaded.

As final touch, the converter also checks to be sure that a resource 
being loaded from the PC has its bit images synchronized to an even byte 
boundary. If this is not corrected, the ST will suffer a bus error when 
attempted to address the images with a word type operation, which will 
certainly happen in either the RCS or the application itself on the 
target system.


\subsection{Operation}

When the Resource Converter loads, it presents an initial dialog box. 
(The converter does not use the menu bar.) The dialog has action buttons 
at the bottom labelled \verb"Help", \verb"Convert" and \verb"Quit". Clicking the Help 
button will obtain a screen which summarizes these operating 
instructions. The \verb"Quit" button terminates the program. Clicking \verb"Convert"
initiates the program's action, according to the options you have set in 
the rest of the dialog.

The top two buttons in the dialog establish the direction of the 
conversion. If you have built a resource on the PC and want to move it 
to the ST, click \verb"Intel->68000". If you are moving the file from the ST to 
the PC, click \verb"68000->Intel".

The next two lines in the dialog establish the file extent names which 
will be used for the conversion. The input extent names are always on 
the left, no matter which conversion mode you selected above. By 
default, they are \verb"RSC" and \verb"DEF". The output extents, on the right, are RS2 
and \verb"DF2" by default. The \verb"RSC/RS2" file extents are used for the resource, 
and \verb"DEF/DF2" extents are for the symbol file. Be careful that the input 
files you use are actually of the type (Intel or 68000) which you 
specified. If you get it backwards, the ST will most likely crash, 
though the input files will not be harmed.

The three buttons below the file extents determine the format of the 
input and output symbol files. If you click on \verb"DEF", the Resource 
Converter will assume that the input and output symbol files are in the 
old (that is, version 1.1) format used by the RCS. If you click on \verb"DFN", 
the program expects the new (version 2.0) symbol format. If the input 
symbol file extent is still set to \verb"DEF", clicking this button will also 
change it appropriately. (Note that the \verb"DEF" and \verb"DFN" formats are in fact 
IDENTICAL on the PC ONLY. To "change formats" ON THE PC, you need only 
change the file's extent name, for example, rename \verb"FOOBAZ.DEF" to 
\verb"FOOBAZ.DFN". On the ST, there is a real difference,and you must use the 
DRI \verb"DEF2DFN.PRG" utility to go from old to new.)

The last button option is (OFF). Clicking this button disables the 
symbol file conversion. You may use this option to keep better control 
over versions of your resource. By establishing the main version on 
either the PC or ST, and converting only the resource file, not the 
symbols, you can ensure that no one will use the RCS on the destination 
machine to create a version which is different from the source.

When the \verb"Convert" button is clicked to begin execution, the standard Item 
Selector is displayed. Use it to find and pick the input resource file 
which you want to convert. The Converter will use its main filename, 
substituting the various extents, to find the input definition file, and 
produce the output file names. If the definition file cannot be found in 
the same directory under the generated name, you will be presented with 
an alert, asking you to abort the conversion, continue without the 
symbol file, or specify a new name and/or directory for the file. If the 
output names coincide with existing files, they will be overwritten.

While the conversion operation is occurring, a progress indicator box 
will be displayed on the screen, with text messages indicating the 
current phase of the operation. When the conversion is complete, you are 
returned to the initial dialog, where you may quit or perform another 
conversion.

One last note on conversion, with a caution: it is possible to move 
files between Intel and 68000 even if you have two different versions of 
the Resource Construction Set, for instance, Version 2.0 on the PC and 
Version 1.1 on the ST. In this situation, you can take advantage of the 
identity between symbol file formats on the PC. Make a copy of the PC 
symbol file into another file with the \verb"DEF" extent, and run the 
converter. The output should load on the ST version correctly. However, 
if you move symbols between different RCS versions, you MUST NOT use the 
"free strings" and "free images" features of version 2 and then move the 
symbols to version 1. Doing so may result in spurious assignment of the 
"free" symbols to trees and objects, and you will (of course) not be 
able to edit the free images and/or strings in the resource.


\subsection{How it works}

For the ST-only developers now rejoining the discussion, I will now take 
a look at the standard GEM initialization code and the special dialog 
handling techniques which I have used in the Converter. Then we'll look 
at the guts of the code, which threads through the resource to do the 
actual conversion. For those interested in the supporting code 
libraries, the GEMDOS interface utilities in {\tt RSCVFILE.C} were described 
earlier. The progress indicator functions of {\tt RCSLIB.C} were 
detailed in the previous chapter, and {\tt map\_tree()} and standard dialog handling 
techniques were discussed in columns three through five.

There are a number of useful facts in {\tt rscv\_init()}, the initialization 
code. First, notice that the result of \verb"appl_init" is NOT assigned 
directly to \verb"gl_apid". Due to a bug in the \verb"appl_init" binding the 
application ID is not returned as the function value. Instead it is 
returned to the global variable \verb"gl_apid". This bug wouldn't cause direct 
problems in the resource converter, but it will in any program which 
uses the ID when sending messages to its own pipe.

Next, an alert string to be displayed if the resource is not found has 
been explicitly included, to avoid a "Catch-22" situation. You can 
easily create such a string by building the alert in the RCS, using the 
C output option, and extracting the string from the resulting file.

{\tt Rscv\_init()} then sets up its VDI handle, by getting the physical 
workstation handle from \verb"graf_handle", and passing it to \verb"v_opnvwk" (open 
virtual workstation), which returns the virtual workstation handle for 
use in VDI calls. \verb"V_opnvwk" also returns the dimensions of the screen, 
which are copied to \verb"GRECT scrn_area", and the number of color planes, 
which is used to set up an \verb"MFDB" for the screen: \verb"scrn_mfdb".

The \verb"wind_get" call for the working area of the DESK window (number zero) 
results in the usable \verb"GRECT" of the screen. This is different from 
\verb"scrn_area", because the menu bar's rectangle is reserved for the system.

You may want to take particular notice of the \verb"vst_height" call, which 
reloads the character dimension variables. The values returned earlier 
by \verb"graf_handle" are ALWAYS for the monochrome (high resolution) system 
font, and they are not appropriate for the low and medium resolution 
modes of the ST. Performing the \verb"vst_height" call AFTER opening the 
virtual workstation will get the correct dimensions.

Some of the environment variables which are set up by {\tt rscv\_init()}, are 
not actually used in the resource converter. I have included them 
because they are part of my "generic" initialization procedures.

Finally, {\tt rscv\_init()} uses \verb"Malloc" to reserve most of memory as a working 
buffer for the resource conversion. Notice that 4K are left free. You 
must leave at least 2K, and preferably a safety factor, or the AES will 
be unable to allocate memory for the file selector dialog, and your 
application will hang when calling \verb"fsel_input". By the way, an open 
virtual workstation uses about 8K, so you should do your \verb"Mallocs" after 
the workstation call.

We now turn our attention to {\tt do\_mode()}, which handles the main dialog of 
the converter. After getting the root address of the dialog tree, the 
states of global variables \verb"conv_def" and \verb"new_dfn" are used to set up the 
radio button array for symbol file conversion. \verb"Native_in" is used to set 
up the conversion type radio buttons. The last initialization step is to 
use the {\tt set\_text()} utility to link the file extent strings into the 
appropriate editable objects. Notice that this version of {\tt set\_text()} 
allows the string length to be explicitly supplied. For an editable text 
field object (\verb"G_FTEXT" or \verb"G_FBOXTEXT"), the length must be one greater 
than the number of blanks in the editing template.

Since there are \verb"TOUCHEXIT" objects in the dialog, we cannot use the 
standard {\tt hndl\_dial()} routine. Instead, the form setup and draw calls are 
coded inline. The actual \verb"form_do" call is placed inside a loop. If the 
object returned is not one of the TOUCHEXIT objects, the loop is 
terminated.

The two objects \verb"DEFYES" and \verb"DFNYES", which select the old and new symbol 
file formats, respectively, have been made \verb"TOUCHEXIT". If either is 
clicked, the radio button processing is done by the AES, but then 
control is returned from \verb"form_do". {\tt Do\_mode()} then tests the current input 
symbol file extent. If it is \verb"DEF" and we are switching from old to new 
mode, the extent is changed to \verb"DFN". When switching from new to old 
mode, the reverse check is made. In either case, the {\tt disp\_obj()} utility 
is used to force an immediate redraw before returning to \verb"form_do" for 
further user input.

When the loop terminates, {\tt do\_mode()} cleans up the screen with \verb"form_dial", 
and uses the {\tt selected()} utility to retrieve the status of the radio 
button arrays and update the global variables. Finally, {\tt map\_tree()} is 
used to apply the deselection utility to all objects in the tree, 
leaving it clean for the next invocation of {\tt do\_mode()}.


\subsection{The Belly of the Beast}

The routine {\tt dconv()} contains the code for actually converting the 
resource. About half of {\tt do\_conv()} is devoted to accessing disk files, 
and correctly handling error conditions which might arise. The error 
recovery could perhaps be handled more concisely with artifices like 
\verb"setjmp", but I have left it in-line for the sake of clarity.

{\tt Do\_conv()} also uses a collection of routines whose names begin with 
\verb"swap_" {\tt Swap\_bytes()} and {\tt swap\_words()} are the workhorse routines. They 
simply run through a given area of memory, reversing every pair of bytes 
or words, respectively. (Remember that the word swapper will only work 
on even byte boundaries, or a bus fault will occur.) The other swap 
routines do the fix up for one type of resource structure each. I'll 
take apart a couple in detail, so that you can see the similarities in 
the others.

Now let's follow the {\tt do\_conv()} code. The first item of business is to 
use the {\tt get\_file()} utility, followed by {\tt open\_file()}, to find and open 
the input resource file. Again, refer to a previous chapter for a discussion 
of these routines, which will handle DOS errors if they occur.

The Boolean \verb"conv_def" is \verb"TRUE" if we need to open a symbols file. If 
everything goes right, just substituting a new extent name (from 
variable \verb"old_def"), and doing the file open will get the file. If things 
foul up, {\tt do\_conv()} has to recover gracefully. So, it puts up the three 
button alert \verb"NODEF". The third button is an abort option; if it's picked 
we punt, closing the one open file and returning to the main dialog. 
Button one allows a continuation without the definition file (\verb"conv_def" 
is forced \verb"FALSE" so the user won't make the same mistake twice). Button 
two says try again, so {\tt get\_file()} is called to pick another file, and 
the whole process repeats.

Once the input file(s) are open, the operation will run to completion, 
assuming no disk errors. The mouse form is switched to an hour glass, 
and a progress indicator box is initialized on the screen.

The first action is to bring in the resource header only. If the 
resource is not native, that is, is not in 68000 format, its bytes must 
be swapped before using any of the counts and offsets. Note: if you've 
never dissected a resource before, this would be a good time take a look 
at the header format given in {\tt gemdefs.h} in the Developer's Kit, and 
the resource structure definitions in {\tt obdefs.h}.

After the swap, if necessary, the resource size field can be used. 
Before reading the rest of the resource, the size must be compared 
against the size of the buffer allocated during initialization. If there 
isn't enough room, the \verb"NOMEM" alert is displayed and control returns to 
the main dialog. (Since the biggest resource is 64K, and the Converter 
is rather small, this shouldn't ever happen. But, some people load up 
lots of desk accessories, so best to be prepared.)

After completing the resource input, an (admittedly kludgy) patch is 
made for the odd-byte-images problem. If the image offset pointer is 
odd, there will be problems on the ST. The fix made here relies on two 
facts. First, all images are an even number of bytes in size. Second, 
the old version of RCS DOES do an even byte synchronization AFTER 
writing the images. Therefore, if the images start on an odd byte, they 
will end on an even byte, and have one unused odd-addressed byte 
immediately following. The fixup strategy is to move all of the images 
up one byte, patch the offset in the header accordingly, and leave the 
\verb"img_odd" flag set so that the bit image swap routine will also increment 
pointers in the \verb"BITBLK" and \verb"ICONBLK"s which use the images.

If the resource being converted is native, we can do the image fixup 
immediately. If not, all of the other swaps have to take first, because 
the long pointers in the \verb"BITBLK"s and \verb"ICONBLK"s are in the wrong order. 
(We don't have to swap string data; it's always stored in ascending 
order.)

{\tt Do\_conv()} calls subroutines to swap the tree index, objects, \verb"TEDINFO"s, 
\verb"ICONBLK"s, \verb"BITBLK"s, and free string and images, in that order. We'll look 
at their actual code later. When this is finished, one of two cleanup 
actions is needed. If the resource WAS native, everything is now swapped 
except the header, which is finally reversed. If it used to be foreign 
(Intel), the pointers are now in proper 68000 order, so {\tt swap\_images()} 
can be called successfully.

Now it's time to write the converted resource, taking care that no error 
results. If no symbol file conversion is needed, {\tt do\_conv()} is done. The 
files are closed, the progress indicator completed, and control returns 
to {\tt rscv\_run()}, which will set the cursor back to the arrow. Otherwise, 
it's time to handle the symbols file.

The first two bytes in the definition file are always the symbol count. 
They are read into \verb"nsym", and a scratch copy is made in reply, and 
swapped. Just which version is written to the output file depends on 
whether it is a \verb"DFN" or \verb"DEF" file. The new (\verb"DFN")
format keeps a similar 
word order on both the ST and PC. For these files, the following code 
amounts to a verbatim copy.

Nsym is now used as the control variable of a loop which reads, 
converts, and writes one symbol entry on each iteration. In the old 
(\verb"DEF") file format, there was an extra word in the value field of each 
symbol's entry on the ST. Going from PC to ST, two padding zero bytes 
are added. Going the other way, they are read and discarded. For the old 
format, both the significant word of this field, as well as the 
following word field (the type) are swapped. The ten symbol bytes are 
passed through verbatim in both new and old format.

After swapping (old format) or simply copying (new format) of the symbol 
file is completed, file and progress box cleanup is done, and control 
returns.


\subsection{The ol' switcheroo}

As promised, let's now go and look at a sampling of the structure swap 
routines: one of the simplest (tree index), one of medium complexity 
(objects), and the worst of the bunch (bit images).

{\tt Swap\_trees()} is responsible for fixing the tree index. Its location is 
found by adding an offset from the header (\verb"rsh_trindex") to the base 
address of the resource, stored in head. (Notice that head was defined 
as a byte pointer when the buffer was allocated, so I need to type 
coerce it to a resource header pointer before making structure 
references.) The number of trees is stored in the \verb"rsh_ntree" header 
field. Each index entry is a long pointer of 32-bits, so the total size 
of the index may be found by multiplication. Finally, the swapping is 
done, first bytes within words, then words within the long pointers. 
(The order doesn't matter - work it out!)

{\tt Swap\_objs()} takes care of swapping fields inside of object structures. 
It begins similarly to {\tt swap\_trees()}, computing the base address of the 
objects from \verb"rsh_object", and taking the count from \verb"rsh_nobs". Since all 
of the objects are contiguous in a resource produced by RCS, and all 
fields of an object are words or longs, a byte swap is performed on the 
entire block at once. Now there are a couple of tricks. Notice that 
\verb"where" in this routine is typed as an object pointer. As the number of 
objects is counted down in the loop, \verb"where" is incremented. Because of 
its type, its actual pointer value will increase by \verb"sizeof(OBJECT)" at 
each iteration. Inside the loop, only one long field, the \verb"ob_spec", needs 
to be word swapped. When the loop completes, all object structures are 
fixed.

{\tt Swap\_fstr()} and {\tt swap\_fimg()} use code similar to {\tt swap\_trees()}. The other 
resource structures, \verb"TEDINFO"s, \verb"ICONBLK"s, and \verb"BITBLK"s, are transformed by 
code similar to {\tt swap\_objs()}. There is one subtlety here. These 
structures would normally be reaching by following an object's \verb"ob_spec" 
pointer. To finesse a "swap now or later" ordering problem with the 
objects, I have instead used the resource header to find the structure 
arrays. You SHOULD NOT use this technique at run time, for two reasons. 
First, if you do any object patching on the fly, the correspondence 
between objects and reference strucutres will be destroyed. Second, 
there is no way to name a non-object structure with the RCS, and 
therefore no way to reliably retrieve it with \verb"rsrc_gaddr" at execution 
time.

Last but not least, {\tt swap\_images()} not only takes care of switching bit 
image words, but also fixes image pointers as necessary if an odd byte 
problem has been detected. For these reasons, {\tt swap\_images} DOES follow 
pointers from the \verb"ICONBLK"s and \verb"BITBLK"s. The loop structure of the two 
sections of code will be familiar from {\tt swap\_ibs()} and {\tt swap\_bbs()}. Size 
fields within the structure are used to determine the length of each 
image. If the \verb"img_odd" flag has been set, the data pointer must be 
incremented BEFORE doing the swap, since the underlying data has already 
been moved.

\newpage

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\begin{appendix}

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\section{Commonly asked Questions}

Q: {\bf The ST RCS does not seem to support multiple screen resolutions 
properly. The spacing between boxes and text is not right. Is this a 
buggy RCS?}

A: Yes, there is a known bug in the RCS with color systems. It is 
(incorrectly) trying to use the character size for monochrome mode, 
which has twice as many vertical pixels. Digital Research is working on 
a fixed version, but for now you must either use a a monochrome system 
with RCS, or do some patches by hand.


Q: {\bf I have created a menu bar using the RCS, and now I need to display it 
using C. How do I go about it?}

A: First, you must find the address of the menu tree using:

\begin{verbatim}
    rsrc_gaddr(R_TREE, MYMENU, &ad_menu);
\end{verbatim}

This assumes that MYMENU is the name you gave your menu in the RCS, and 
that \verb"ad_menu" is a LONG variable. Then you make the call:

\begin{verbatim}
    menu_bar(ad_menu, TRUE);
\end{verbatim}

which will cause GEM to draw the menu and begin sending menu messages to 
your application. When your program is done, remove the menu bar with:

\begin{verbatim}
    menu_bar(0x0L, FALSE);
\end{verbatim}

before terminating. 


Q: {\bf What is the WM\_NEWTOP message? How is it different from WM\_TOPPED?}

A: WM\_NEWTOP is a message which is sent to an application when one of 
its windows is about to be REMOVED from the top position. Most programs 
may safely ignore this message. It is meant for use by "Paint-like" 
programs which use a window as an active buffer area and must be able to 
save away its contents before they are overlaid by a desk accessory or 
another window. WM\_NEWTOP contrasts with WM\_TOPPED, which is sent when 
the window is about to be PLACED in the top position.


Q: {\bf In RCS, what is the format of the {\tt .ICN} files which can
 be used with the LOAD option for icons and bit images?}

A: The RCS expects the {\tt .ICN} files to be in an obscure ASCII hexadecimal 
format which is produced by the GEM IconEditor. Unfortunately, the 
IconEditor has not yet been ported to the ST. So that you can get an 
idea of this format, I have included the images of two {\tt .ICN} files within 
the listings. You might try to extract the text and load them  into RCS 
as the data and mask for an icon. If you do it right, you should see a 
clock face.

If you want to build your own {\tt .ICN} files, you must keep the rigid four 
number per line format while adding and removing data lines. You may 
change the vertical and horizontal pixel counts, but the  horizontal 
count must always be a multiple of sixteen. Finally, the RCS expects the 
images to be in device-independent, monochrome format.


Q: {\bf The AES manual states "when the application is first loaded into 
memory, it should make a DOS call to modify the application's memory 
allocation". How is this done?}

A: When a GEM application is first loaded by the AES, all of memory is 
allocated to it. It must then release that portion which is  past the 
end of its field length. This is necessary since the AES file selector 
and the VDI open workstation and load fonts calls allocate memory, and 
the application itself may need to do its own memory management.

Fortunately, the standard routine APSTART will release memory for you if 
it is included as the first item in your link. It uses a setblock call 
to TOS, after determining the proper length of your application. To do 
so (quoting from APSTART), all "segment" lengths in  the base page are 
totaled and 0x100 is added for the base page length.


Q: {\bf Is it possible to patch GEM so that you must first click on the menu 
bar to active a drop-down, rather than just touching it with the cursor?  
I find it mildly irritating to open a drop-down menu accidently when I 
am merely moving the cursor around.}

A: As you may have guessed from the preceding discussion, the GEM menu 
algorithm is embedded deeply in the AES code and is not patchable. The 
"drop-down" architecture was chosen over "pull-downs" because it proved 
easier for novices. Unfortunately, it does cause problems for 
experienced users who mouse around the screen much faster.

One way to  partially avoid the problem is to design applications which 
have some  separation space between the menu bar and selectable objects. 
On the Desktop, you can move file windows away from the bar and then 
save the new layout.


Q: {\bf How can I support multiple resolutions if I need to include icons and 
images in my resource?  Do I need to have an entire separate resource 
for each resolution, or is there a simpler way?}

A: It is certainly possible to have an alternate resource for each 
screen mode, but it introduces problems in keeping their structure and 
naming identical. Instead, you might consider building separate files 
containing only the bit image data for your resource, with one version 
for each resolution. You might do this by copying the image definitions 
from the {\tt .C} file emitted by the RCS.

After you have loaded the resource, allocate some memory and  read in 
the appropriate image file. You will then have to link in the  image 
data by modifying the pointers in your resource's BITBLK and  ICONBLK 
structures. You will need to determine in advance which objects  must be 
modified, and in what order their data occurs in the image file.


Q: {\bf Why are there separate startup procedures for applications and desk 
accessories ({\tt APSTART.S} and {\tt ACCSTART.S})?}

A: A desk accessory is started up automatically when GEM is booted, and 
becomes more or less part of the system. An application is only run at 
the user's request, after the system has finished loading. Since they 
start at different times, they have a different "environment" to contend 
with. For instance, the application startup code has to release memory 
following the program, while the accessory has this done for it by GEM.


Q: {\bf Can a desk accessory use a resource?}

A: In general, no. This is because the accessories are loaded at system 
initialization time. If one later makes a {\tt rsrc\_load()} call for its 
resource, the system would allocate the resource's buffer in the user 
area of memory. This would result in a memory allocation error when the 
next application attempted to run.

However, it is still possible to use AES object trees within an 
accessory. You should use the RCS to create the trees, then use the C 
output option to create an image of them. This image may be included and 
compiled in the accessory's source code. At run time, you will have to 
adjust the size of the objects using {\tt rsrc\_obfix()}, as well as fix up the 
inter-structure pointers. You can use the source code of {\tt STCREATE.C} and 
the discussion of resource structure in a prior column as guides.


Q: {\bf Are there problems with the {\tt--f} (floating point)
     option in Alcyon C?}

A: Yes, there are a number of bugs in the Alcyon floating point library. 
In many cases, the precision of operations is poor. The only solution is 
to switch to Megamax or Lattice C to develop your floating point 
application.


Q: {\bf I've noticed that the HEAD, TAIL, and NEXT pointers in an object tree 
are actually numbers relative to the base of the tree. Does this mean 
that an object must be pre-allocated within the tree if I plan to 
{\tt objc\_add()} it later? Can an application do true dynamic allocation of 
objects without setting aside space in the tree?}

A: Yes, you must preallocate objects if you want to add them without 
moving the tree from the resource. The alternative is to create a 
working area from your program and copy the tree to be altered to this 
buffer. Then you can allocate new objects following those which exist, 
and link them in. The new objects must be created on 24-byte boundaries 
starting at the root of the tree. You do NOT need to copy over 
structures such as TEDINFOs, unless you plan to modify them also.


Q: {\bf I'm using the Atari Developer's Kit, and LINK68 seems to crash when 
my programs get large. Is this a bug?}

A: Yes, there is a known bug in using Alcyon C and LINK68 when a 
program's code area approaches 64K. It appears that jump tables 
generated by SWITCH and GOTO statements are not being properly 
relocated. Often the difficulty can be avoided by putting such modules 
at the start of the link. Otherwise, you will need to to recode SWITCH 
statements as IFs, and eliminate the GOTOs (a good practice anyway).

%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

\section{Listings of example source files}

Your disk should contain the following example source files:

\begin{verbatim}
\
  GEMCL02.C
  GEMCL03.C
  GEMCL04.C
  GEMCL05.C
  GEMCL06.C
  GEMCL07.C
  GEMCL09.C
  GEMCL10.C
  GEMCL11.C
  GEMCL13.C
  GEMCL15.C
GEMCL16\
  GMCL16.C
  GMCL16.H
  GMCL16.RSC
  GMCL16.RSH
  GMCL16.DFN

GEMCL17\
   RSCVFILE.C
   RSCVLIB.C
   RSCVMAIN.C
   RSCONV.H
   RSCVLINK.SH
   RSCONV.PRG
   RSCONV.RSC
   RSCONV.DFN

\end{verbatim}

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

% \newpage
% \include{app_a}
% \include{app_b}
% \include{app_c}

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\end{appendix}

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\end{document}
